new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Pydantic · Concepts · all subjects

performance

12 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Use model_validate_json() for better performance than model_validate(json.loads())

When validating JSON, use model_validate_json() instead of model_validate(json.loads(...)). The json.loads approach parses JSON in Python, converts it to a dict, then validates internally. model_validate_json() performs validation internally and is generally faster. There are specific edge cases where model_validate(json.loads(...)) may be faster: when using 'before' or 'wrap' validators on a model. As performance improvements continue in pydantic-core, model_validate_json() should become consistently faster than the two-step method.

Prefer list/tuple over Sequence and dict over Mapping for performance

When the value type is known, use specific collection types instead of abstract ones. Use list or tuple instead of Sequence because Pydantic must call isinstance(value, Sequence) checks and validate against multiple sequence types. Similarly, use dict instead of Mapping. This avoids unnecessary type checking and validation overhead.

Avoid extra information via subclasses of primitives

Do not create subclasses of primitive types (like str) to store extra information. Instead, use a BaseModel with separate fields for the primitive value and the extra information. This avoids performance overhead and is cleaner structurally.

Use tagged union instead of plain union for better performance

Use tagged unions (discriminated unions) with a discriminator field instead of plain unions without discriminators. Tagged unions use a field like el_type with Literal values to indicate the specific type, allowing Pydantic to validate more efficiently by checking the discriminator first.

Use TypedDict over nested BaseModel for performance

For nested data structures, TypedDict is approximately 2.5x faster than nested BaseModel classes. A benchmark shows TypeAdapter validating a TypedDict with nested structure is significantly faster than using nested BaseModel classes.

Avoid wrap validators for performance-critical code

Wrap validators are generally slower than other validator types because they require data to be materialized in Python during validation. While wrap validators are useful for complex validation logic, avoid them when performance is critical.

Use FailFast annotation for early exit in sequence validation

Starting in v2.8+, apply the FailFast annotation to sequence types to exit validation immediately when the first item fails. Example: Annotated[list[bool], FailFast()] will stop validating remaining items after the first failure. This trades off error visibility for performance by not collecting all validation errors.

FailFast example with list[bool]

from typing import Annotated from pydantic import FailFast, TypeAdapter, ValidationError ta = TypeAdapter(Annotated[list[bool], FailFast()]) try: ta.validate_python([True, 'invalid', False, 'also invalid']) except ValidationError as exc: print(exc) # Output shows only the first validation error at index 1, not errors for subsequent items

Use Logfire to identify Pydantic validation bottlenecks

Logfire records the duration of each Pydantic validation as a span. Use this tool to identify where validation time actually goes in a running application before optimizing.

Accessing raw_function attribute

The original undecorated function can be accessed via the raw_function attribute of a validate_call decorated function. This is useful when you trust your input arguments and want to call the function without validation overhead for performance reasons.

validate_call performance impact

While function inspection is only performed once, there is a performance impact when calling a validate_call decorated function compared to calling the original function. In many situations this has little or no noticeable effect, but validate_call is not an equivalent or alternative to function definitions in strongly typed languages.

validate_call example with raw_function

Example accessing raw_function to call without validation: from pydantic import validate_call @validate_call def repeat(s: str, count: int, *, separator: bytes = b'') -> bytes: b = s.encode() return separator.join(b for _ in range(count)) result = repeat.raw_function('good bye', 2, separator=b', ') This calls the original undecorated function without validation.

Give your agent this brain