backend / web frameworks / pydantic / 03_validation_modes.md

What is the difference between Pydantic validation modes "before" vs "after"?

3 interview angles 2 min read source

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 an int field gets the raw value; you can convert "42"42 or 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 an int field gets an int; you can check v >= 0 or 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

  • before or after validators?” - before sees the raw input and is where you normalise or coerce unusual formats; after sees 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" to 1); 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.