What is the difference between Pydantic validation modes “before” vs “after”?
Answer
In Pydantic v2, validation mode controls when validators run relative to the initial parsing/coercion of raw input into Python types.
“Before” (default: mode='before')
- The validator runs before Pydantic’s built-in coercion. It receives the raw value as it came in (e.g. string
"42"or dict{"x": 1}). - Use when you want to normalize or reject input before it’s turned into the field type (e.g. strip whitespace from strings, reject invalid formats early, or convert one representation into another before coercion).
- Example: a
field_validator(mode='before')on anintfield gets the raw value; you can convert"42"→42or raise if it’s not a number-like string.
“After” (e.g. mode='after')
- The validator runs after Pydantic has already coerced the value to the field’s type. It receives the parsed value (e.g. actual
int,datetime, or nested model). - Use when you want to constrain or refine the value once it’s already the right type (e.g. check
age >= 0, clamp a number to a range, or validate relationships between fields). - Example: a
field_validator(mode='after')on anintfield gets anint; you can checkv >= 0or adjust it.
Summary
- Before: raw input → your validator → Pydantic coercion → field value. Good for pre-processing and early rejection.
- After: raw input → Pydantic coercion → your validator → field value. Good for post-coercion checks and business rules.
Model validators can also use mode='before' (entire raw data) or mode='after' (fully constructed model) for whole-model validation.
Interview angle
- “
beforeoraftervalidators?” -beforesees the raw input and is where you normalise or coerce unusual formats;aftersees the parsed, typed value and is where business rules belong. Choosing wrong means either fighting the parser or validating a value that never parsed. - “Strict or lax mode?” - lax coerces where it can (the string
"1"to1); strict rejects type mismatches. Strict is safer for internal contracts where a type mismatch signals a bug; lax is pragmatic at messy external boundaries. - “Field-level or model-level validation?” - field-level for one value in isolation, model-level for rules spanning fields such as end date after start date. Model-level runs after all fields have been validated individually.