[{"data":1,"prerenderedAt":1696},["ShallowReactive",2],{"nav":3,"page-\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fmodel-construct-when-to-skip-validation\u002F":580,"surround-\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fmodel-construct-when-to-skip-validation\u002F":1695},[4,186,386],{"title":5,"path":6,"stem":7,"children":8},"Advanced Pydantic Validation Serialization","\u002Fadvanced-pydantic-validation-serialization","advanced-pydantic-validation-serialization",[9,12,42,66,90,114,150,174],{"title":10,"path":6,"stem":11},"Advanced Pydantic Validation and Serialization","advanced-pydantic-validation-serialization\u002Findex",{"title":13,"path":14,"stem":15,"children":16},"Custom Validators and Field Constraints in Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Findex",[17,18,24,30,36],{"title":13,"path":14,"stem":15},{"title":19,"path":20,"stem":21,"children":22},"Before, After and Wrap Validators in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fbefore-after-and-wrap-validators","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fbefore-after-and-wrap-validators\u002Findex",[23],{"title":19,"path":20,"stem":21},{"title":25,"path":26,"stem":27,"children":28},"Creating Reusable Custom Validators in Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcreating-reusable-custom-validators-in-pydantic","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcreating-reusable-custom-validators-in-pydantic\u002Findex",[29],{"title":25,"path":26,"stem":27},{"title":31,"path":32,"stem":33,"children":34},"Cross-Field Validation Patterns in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcross-field-validation-patterns","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcross-field-validation-patterns\u002Findex",[35],{"title":31,"path":32,"stem":33},{"title":37,"path":38,"stem":39,"children":40},"Pydantic v2 Async Custom Validator: What to Do Instead","\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fpydantic-v2-async-custom-validator","advanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fpydantic-v2-async-custom-validator\u002Findex",[41],{"title":37,"path":38,"stem":39},{"title":43,"path":44,"stem":45,"children":46},"JSON Schema Customization in Pydantic and FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Findex",[47,48,54,60],{"title":43,"path":44,"stem":45},{"title":49,"path":50,"stem":51,"children":52},"Customizing OpenAPI Schema Generation in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fcustomizing-openapi-schema-generation-in-fastapi","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fcustomizing-openapi-schema-generation-in-fastapi\u002Findex",[53],{"title":49,"path":50,"stem":51},{"title":55,"path":56,"stem":57,"children":58},"Discriminated Unions in OpenAPI with Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fdiscriminated-unions-in-openapi","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fdiscriminated-unions-in-openapi\u002Findex",[59],{"title":55,"path":56,"stem":57},{"title":61,"path":62,"stem":63,"children":64},"Examples in the OpenAPI Schema with FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fexamples-in-openapi-schema","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Fexamples-in-openapi-schema\u002Findex",[65],{"title":61,"path":62,"stem":63},{"title":67,"path":68,"stem":69,"children":70},"Nested Model Serialization in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Findex",[71,72,78,84],{"title":67,"path":68,"stem":69},{"title":73,"path":74,"stem":75,"children":76},"Excluding Fields Per Endpoint in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fexcluding-fields-per-endpoint","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fexcluding-fields-per-endpoint\u002Findex",[77],{"title":73,"path":74,"stem":75},{"title":79,"path":80,"stem":81,"children":82},"Handling Deeply Nested JSON Models Efficiently","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fhandling-deeply-nested-json-models-efficiently","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fhandling-deeply-nested-json-models-efficiently\u002Findex",[83],{"title":79,"path":80,"stem":81},{"title":85,"path":86,"stem":87,"children":88},"Self-Referencing and Recursive Models in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fself-referencing-and-recursive-models","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fself-referencing-and-recursive-models\u002Findex",[89],{"title":85,"path":86,"stem":87},{"title":91,"path":92,"stem":93,"children":94},"Performance Optimization for Pydantic Models in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Findex",[95,96,102,108],{"title":91,"path":92,"stem":93},{"title":97,"path":98,"stem":99,"children":100},"model_construct and When to Skip Validation in Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fmodel-construct-when-to-skip-validation","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fmodel-construct-when-to-skip-validation\u002Findex",[101],{"title":97,"path":98,"stem":99},{"title":103,"path":104,"stem":105,"children":106},"Pydantic Model Serialization Performance in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance\u002Findex",[107],{"title":103,"path":104,"stem":105},{"title":109,"path":110,"stem":111,"children":112},"TypeAdapter for Non-Model Types in Pydantic","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Ftypeadapter-for-non-model-types","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Ftypeadapter-for-non-model-types\u002Findex",[113],{"title":109,"path":110,"stem":111},{"title":115,"path":116,"stem":117,"children":118},"Pydantic V2 Migration Guide for FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Findex",[119,120,126,132,138,144],{"title":115,"path":116,"stem":117},{"title":121,"path":122,"stem":123,"children":124},"Migrate @validator to @field_validator in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrate-validator-to-field-validator","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrate-validator-to-field-validator\u002Findex",[125],{"title":121,"path":122,"stem":123},{"title":127,"path":128,"stem":129,"children":130},"Migrating from Pydantic v1 to v2 Without Breaking APIs","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrating-from-pydantic-v1-to-v2-without-breaking-apis","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmigrating-from-pydantic-v1-to-v2-without-breaking-apis\u002Findex",[131],{"title":127,"path":128,"stem":129},{"title":133,"path":134,"stem":135,"children":136},"model_config vs class Config in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmodel-config-vs-class-config","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Fmodel-config-vs-class-config\u002Findex",[137],{"title":133,"path":134,"stem":135},{"title":139,"path":140,"stem":141,"children":142},"Replacing json_encoders with field_serializer in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Freplacing-json-encoders-with-field-serializer","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Freplacing-json-encoders-with-field-serializer\u002Findex",[143],{"title":139,"path":140,"stem":141},{"title":145,"path":146,"stem":147,"children":148},"Migrating @root_validator to @model_validator in Pydantic v2","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Froot-validator-to-model-validator","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Froot-validator-to-model-validator\u002Findex",[149],{"title":145,"path":146,"stem":147},{"title":151,"path":152,"stem":153,"children":154},"Request Validation Patterns in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Frequest-validation-patterns","advanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Findex",[155,156,162,168],{"title":151,"path":152,"stem":153},{"title":157,"path":158,"stem":159,"children":160},"Optional vs Nullable Fields in Pydantic and FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Foptional-vs-nullable-fields","advanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Foptional-vs-nullable-fields\u002Findex",[161],{"title":157,"path":158,"stem":159},{"title":163,"path":164,"stem":165,"children":166},"Query, Path and Body Parameter Validation in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Fquery-path-and-body-parameter-validation","advanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Fquery-path-and-body-parameter-validation\u002Findex",[167],{"title":163,"path":164,"stem":165},{"title":169,"path":170,"stem":171,"children":172},"Validating File Uploads and Forms in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Fvalidating-file-uploads-and-forms","advanced-pydantic-validation-serialization\u002Frequest-validation-patterns\u002Fvalidating-file-uploads-and-forms\u002Findex",[173],{"title":169,"path":170,"stem":171},{"title":175,"path":176,"stem":177,"children":178},"Type Hinting and IDE Integration in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration","advanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration\u002Findex",[179,180],{"title":175,"path":176,"stem":177},{"title":181,"path":182,"stem":183,"children":184},"Annotated Dependencies and Reusable Types in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration\u002Fannotated-dependencies-and-reusable-types","advanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration\u002Fannotated-dependencies-and-reusable-types\u002Findex",[185],{"title":181,"path":182,"stem":183},{"title":187,"path":188,"stem":189,"children":190},"Async Background Tasks Observability","\u002Fasync-background-tasks-observability","async-background-tasks-observability",[191,194,224,254,284,308,338,362],{"title":192,"path":188,"stem":193},"Async, Background Tasks, and Observability in FastAPI","async-background-tasks-observability\u002Findex",{"title":195,"path":196,"stem":197,"children":198},"Async Correctness and Concurrency in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Findex",[199,200,206,212,218],{"title":195,"path":196,"stem":197},{"title":201,"path":202,"stem":203,"children":204},"Concurrent Requests with asyncio.gather in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency\u002Fconcurrent-requests-with-asyncio-gather","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Fconcurrent-requests-with-asyncio-gather\u002Findex",[205],{"title":201,"path":202,"stem":203},{"title":207,"path":208,"stem":209,"children":210},"FastAPI async def vs def: Performance and When to Use Each","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency\u002Ffastapi-async-def-vs-def-performance","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Ffastapi-async-def-vs-def-performance\u002Findex",[211],{"title":207,"path":208,"stem":209},{"title":213,"path":214,"stem":215,"children":216},"Fixing Blocking Calls in Async FastAPI Routes","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency\u002Ffixing-blocking-calls-in-async-routes","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Ffixing-blocking-calls-in-async-routes\u002Findex",[217],{"title":213,"path":214,"stem":215},{"title":219,"path":220,"stem":221,"children":222},"Running Sync Code in a Threadpool in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency\u002Frunning-sync-code-in-a-threadpool","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Frunning-sync-code-in-a-threadpool\u002Findex",[223],{"title":219,"path":220,"stem":221},{"title":225,"path":226,"stem":227,"children":228},"Async Database Sessions in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions","async-background-tasks-observability\u002Fasync-database-sessions\u002Findex",[229,230,236,242,248],{"title":225,"path":226,"stem":227},{"title":231,"path":232,"stem":233,"children":234},"Async SQLAlchemy Session per Request in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Fasync-sqlalchemy-session-per-request","async-background-tasks-observability\u002Fasync-database-sessions\u002Fasync-sqlalchemy-session-per-request\u002Findex",[235],{"title":231,"path":232,"stem":233},{"title":237,"path":238,"stem":239,"children":240},"Fixing asyncpg Connection Pool Exhaustion in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Ffixing-asyncpg-pool-exhaustion","async-background-tasks-observability\u002Fasync-database-sessions\u002Ffixing-asyncpg-pool-exhaustion\u002Findex",[241],{"title":237,"path":238,"stem":239},{"title":243,"path":244,"stem":245,"children":246},"Testing with Async Database Fixtures in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Ftesting-with-async-database-fixtures","async-background-tasks-observability\u002Fasync-database-sessions\u002Ftesting-with-async-database-fixtures\u002Findex",[247],{"title":243,"path":244,"stem":245},{"title":249,"path":250,"stem":251,"children":252},"Transaction Management and Rollback in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Ftransaction-management-and-rollback","async-background-tasks-observability\u002Fasync-database-sessions\u002Ftransaction-management-and-rollback\u002Findex",[253],{"title":249,"path":250,"stem":251},{"title":255,"path":256,"stem":257,"children":258},"Background Task Processing in FastAPI","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing","async-background-tasks-observability\u002Fbackground-task-processing\u002Findex",[259,260,266,272,278],{"title":255,"path":256,"stem":257},{"title":261,"path":262,"stem":263,"children":264},"FastAPI BackgroundTasks vs Celery vs ARQ","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing\u002Ffastapi-backgroundtasks-vs-celery-vs-arq","async-background-tasks-observability\u002Fbackground-task-processing\u002Ffastapi-backgroundtasks-vs-celery-vs-arq\u002Findex",[265],{"title":261,"path":262,"stem":263},{"title":267,"path":268,"stem":269,"children":270},"Retry and Idempotency for FastAPI Background Tasks","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing\u002Fretry-and-idempotency-for-tasks","async-background-tasks-observability\u002Fbackground-task-processing\u002Fretry-and-idempotency-for-tasks\u002Findex",[271],{"title":267,"path":268,"stem":269},{"title":273,"path":274,"stem":275,"children":276},"Running ARQ Workers with FastAPI","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing\u002Frunning-arq-workers-with-fastapi","async-background-tasks-observability\u002Fbackground-task-processing\u002Frunning-arq-workers-with-fastapi\u002Findex",[277],{"title":273,"path":274,"stem":275},{"title":279,"path":280,"stem":281,"children":282},"When FastAPI BackgroundTasks Silently Fails","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing\u002Fwhen-backgroundtasks-silently-fails","async-background-tasks-observability\u002Fbackground-task-processing\u002Fwhen-backgroundtasks-silently-fails\u002Findex",[283],{"title":279,"path":280,"stem":281},{"title":285,"path":286,"stem":287,"children":288},"Caching Strategies in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies","async-background-tasks-observability\u002Fcaching-strategies\u002Findex",[289,290,296,302],{"title":285,"path":286,"stem":287},{"title":291,"path":292,"stem":293,"children":294},"Cache Invalidation Patterns in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies\u002Fcache-invalidation-patterns-in-fastapi","async-background-tasks-observability\u002Fcaching-strategies\u002Fcache-invalidation-patterns-in-fastapi\u002Findex",[295],{"title":291,"path":292,"stem":293},{"title":297,"path":298,"stem":299,"children":300},"Caching Dependency Results in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies\u002Fcaching-dependency-results","async-background-tasks-observability\u002Fcaching-strategies\u002Fcaching-dependency-results\u002Findex",[301],{"title":297,"path":298,"stem":299},{"title":303,"path":304,"stem":305,"children":306},"Redis Response Caching in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies\u002Fredis-response-caching-in-fastapi","async-background-tasks-observability\u002Fcaching-strategies\u002Fredis-response-caching-in-fastapi\u002Findex",[307],{"title":303,"path":304,"stem":305},{"title":309,"path":310,"stem":311,"children":312},"Observability and Tracing in FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing","async-background-tasks-observability\u002Fobservability-and-tracing\u002Findex",[313,314,320,326,332],{"title":309,"path":310,"stem":311},{"title":315,"path":316,"stem":317,"children":318},"Correlating Logs, Traces and Errors in FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing\u002Fcorrelating-logs-traces-and-errors","async-background-tasks-observability\u002Fobservability-and-tracing\u002Fcorrelating-logs-traces-and-errors\u002Findex",[319],{"title":315,"path":316,"stem":317},{"title":321,"path":322,"stem":323,"children":324},"Instrumenting FastAPI with OpenTelemetry","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing\u002Finstrumenting-fastapi-with-opentelemetry","async-background-tasks-observability\u002Fobservability-and-tracing\u002Finstrumenting-fastapi-with-opentelemetry\u002Findex",[325],{"title":321,"path":322,"stem":323},{"title":327,"path":328,"stem":329,"children":330},"Prometheus Metrics for FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing\u002Fprometheus-metrics-for-fastapi","async-background-tasks-observability\u002Fobservability-and-tracing\u002Fprometheus-metrics-for-fastapi\u002Findex",[331],{"title":327,"path":328,"stem":329},{"title":333,"path":334,"stem":335,"children":336},"Structured JSON Logging with Request IDs in FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing\u002Fstructured-json-logging-with-request-ids","async-background-tasks-observability\u002Fobservability-and-tracing\u002Fstructured-json-logging-with-request-ids\u002Findex",[337],{"title":333,"path":334,"stem":335},{"title":339,"path":340,"stem":341,"children":342},"Rate Limiting and Throttling in FastAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling","async-background-tasks-observability\u002Frate-limiting-throttling\u002Findex",[343,344,350,356],{"title":339,"path":340,"stem":341},{"title":345,"path":346,"stem":347,"children":348},"FastAPI Rate Limiting with Redis and SlowAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling\u002Ffastapi-rate-limiting-with-redis-slowapi","async-background-tasks-observability\u002Frate-limiting-throttling\u002Ffastapi-rate-limiting-with-redis-slowapi\u002Findex",[349],{"title":345,"path":346,"stem":347},{"title":351,"path":352,"stem":353,"children":354},"Per-User Token Bucket Throttling in FastAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling\u002Fper-user-token-bucket-throttling","async-background-tasks-observability\u002Frate-limiting-throttling\u002Fper-user-token-bucket-throttling\u002Findex",[355],{"title":351,"path":352,"stem":353},{"title":357,"path":358,"stem":359,"children":360},"Rate Limit Headers and 429 Responses in FastAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling\u002Frate-limit-headers-and-429-responses","async-background-tasks-observability\u002Frate-limiting-throttling\u002Frate-limit-headers-and-429-responses\u002Findex",[361],{"title":357,"path":358,"stem":359},{"title":363,"path":364,"stem":365,"children":366},"Testing FastAPI Applications","\u002Fasync-background-tasks-observability\u002Ftesting-fastapi-applications","async-background-tasks-observability\u002Ftesting-fastapi-applications\u002Findex",[367,368,374,380],{"title":363,"path":364,"stem":365},{"title":369,"path":370,"stem":371,"children":372},"Mocking External Services in FastAPI Tests","\u002Fasync-background-tasks-observability\u002Ftesting-fastapi-applications\u002Fmocking-external-services-in-tests","async-background-tasks-observability\u002Ftesting-fastapi-applications\u002Fmocking-external-services-in-tests\u002Findex",[373],{"title":369,"path":370,"stem":371},{"title":375,"path":376,"stem":377,"children":378},"TestClient vs httpx AsyncClient in FastAPI","\u002Fasync-background-tasks-observability\u002Ftesting-fastapi-applications\u002Ftestclient-vs-httpx-asyncclient","async-background-tasks-observability\u002Ftesting-fastapi-applications\u002Ftestclient-vs-httpx-asyncclient\u002Findex",[379],{"title":375,"path":376,"stem":377},{"title":381,"path":382,"stem":383,"children":384},"Testing Async FastAPI Endpoints with pytest-asyncio","\u002Fasync-background-tasks-observability\u002Ftesting-fastapi-applications\u002Ftesting-async-endpoints-with-pytest-asyncio","async-background-tasks-observability\u002Ftesting-fastapi-applications\u002Ftesting-async-endpoints-with-pytest-asyncio\u002Findex",[385],{"title":381,"path":382,"stem":383},{"title":387,"path":388,"stem":389,"children":390},"Core Architecture Routing Patterns","\u002Fcore-architecture-routing-patterns","core-architecture-routing-patterns",[391,394,412,436,472,496,526,556],{"title":392,"path":388,"stem":393},"FastAPI Core Architecture and Routing Patterns","core-architecture-routing-patterns\u002Findex",{"title":395,"path":396,"stem":397,"children":398},"Application Factory Patterns in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Findex",[399,400,406],{"title":395,"path":396,"stem":397},{"title":401,"path":402,"stem":403,"children":404},"FastAPI App Factory Pattern for Testing and Deployment","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Ffastapi-app-factory-pattern-for-testing-and-deployment","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Ffastapi-app-factory-pattern-for-testing-and-deployment\u002Findex",[405],{"title":401,"path":402,"stem":403},{"title":407,"path":408,"stem":409,"children":410},"Lifespan Events vs Startup and Shutdown in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Flifespan-events-vs-startup-shutdown","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Flifespan-events-vs-startup-shutdown\u002Findex",[411],{"title":407,"path":408,"stem":409},{"title":413,"path":414,"stem":415,"children":416},"Configuration Management in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management","core-architecture-routing-patterns\u002Fconfiguration-management\u002Findex",[417,418,424,430],{"title":413,"path":414,"stem":415},{"title":419,"path":420,"stem":421,"children":422},"Managing Environment Variables with Pydantic Settings","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management\u002Fmanaging-environment-variables-with-pydantic-settings","core-architecture-routing-patterns\u002Fconfiguration-management\u002Fmanaging-environment-variables-with-pydantic-settings\u002Findex",[423],{"title":419,"path":420,"stem":421},{"title":425,"path":426,"stem":427,"children":428},"Pydantic Settings vs Dynaconf vs python-decouple","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management\u002Fpydantic-settings-vs-dynaconf-vs-python-decouple","core-architecture-routing-patterns\u002Fconfiguration-management\u002Fpydantic-settings-vs-dynaconf-vs-python-decouple\u002Findex",[429],{"title":425,"path":426,"stem":427},{"title":431,"path":432,"stem":433,"children":434},"Secrets and .env Files Per Environment in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management\u002Fsecrets-and-env-files-per-environment","core-architecture-routing-patterns\u002Fconfiguration-management\u002Fsecrets-and-env-files-per-environment\u002Findex",[435],{"title":431,"path":432,"stem":433},{"title":437,"path":438,"stem":439,"children":440},"Dependency Injection Strategies in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Findex",[441,442,448,454,460,466],{"title":437,"path":438,"stem":439},{"title":443,"path":444,"stem":445,"children":446},"Best Practices for FastAPI Dependency Injection","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fbest-practices-for-fastapi-dependency-injection","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fbest-practices-for-fastapi-dependency-injection\u002Findex",[447],{"title":443,"path":444,"stem":445},{"title":449,"path":450,"stem":451,"children":452},"Dependency Caching and use_cache in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fdependency-caching-and-use-cache","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fdependency-caching-and-use-cache\u002Findex",[453],{"title":449,"path":450,"stem":451},{"title":455,"path":456,"stem":457,"children":458},"Fixing FastAPI Dependency Injection Circular Imports","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Ffastapi-dependency-injection-circular-import-fix","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Ffastapi-dependency-injection-circular-import-fix\u002Findex",[459],{"title":455,"path":456,"stem":457},{"title":461,"path":462,"stem":463,"children":464},"Overriding Dependencies in FastAPI Tests","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Foverriding-dependencies-in-tests","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Foverriding-dependencies-in-tests\u002Findex",[465],{"title":461,"path":462,"stem":463},{"title":467,"path":468,"stem":469,"children":470},"Yield Dependencies and Cleanup Order in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fyield-dependencies-and-cleanup-order","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Fyield-dependencies-and-cleanup-order\u002Findex",[471],{"title":467,"path":468,"stem":469},{"title":473,"path":474,"stem":475,"children":476},"Error Handling and Global Exceptions in FastAPI","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Findex",[477,478,484,490],{"title":473,"path":474,"stem":475},{"title":479,"path":480,"stem":481,"children":482},"Customising Validation Error Responses in FastAPI","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fcustomising-validation-error-responses","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fcustomising-validation-error-responses\u002Findex",[483],{"title":479,"path":480,"stem":481},{"title":485,"path":486,"stem":487,"children":488},"Global Exception Handlers for Consistent API Responses","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fglobal-exception-handlers-for-consistent-api-responses","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fglobal-exception-handlers-for-consistent-api-responses\u002Findex",[489],{"title":485,"path":486,"stem":487},{"title":491,"path":492,"stem":493,"children":494},"HTTPException vs Custom Exception Classes in FastAPI","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fhttpexception-vs-custom-exception-classes","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Fhttpexception-vs-custom-exception-classes\u002Findex",[495],{"title":491,"path":492,"stem":493},{"title":497,"path":498,"stem":499,"children":500},"Middleware Implementation in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Findex",[501,502,508,514,520],{"title":497,"path":498,"stem":499},{"title":503,"path":504,"stem":505,"children":506},"CORS Middleware Configuration in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fcors-middleware-configuration","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fcors-middleware-configuration\u002Findex",[507],{"title":503,"path":504,"stem":505},{"title":509,"path":510,"stem":511,"children":512},"Implementing Custom Middleware for Request Tracing","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fimplementing-custom-middleware-for-request-tracing","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fimplementing-custom-middleware-for-request-tracing\u002Findex",[513],{"title":509,"path":510,"stem":511},{"title":515,"path":516,"stem":517,"children":518},"Middleware Execution Order in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fmiddleware-execution-order","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fmiddleware-execution-order\u002Findex",[519],{"title":515,"path":516,"stem":517},{"title":521,"path":522,"stem":523,"children":524},"Middleware vs Dependencies: When to Use Which","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fmiddleware-vs-dependencies-when-to-use-which","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Fmiddleware-vs-dependencies-when-to-use-which\u002Findex",[525],{"title":521,"path":522,"stem":523},{"title":527,"path":528,"stem":529,"children":530},"Modular Router Organization in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Findex",[531,532,538,544,550],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"APIRouter Prefix vs Sub-Application Mounting in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Fapirouter-prefix-vs-sub-application-mounting","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Fapirouter-prefix-vs-sub-application-mounting\u002Findex",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541,"children":542},"How to Structure Large FastAPI Projects for Scale","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Fhow-to-structure-large-fastapi-projects-for-scale","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Fhow-to-structure-large-fastapi-projects-for-scale\u002Findex",[543],{"title":539,"path":540,"stem":541},{"title":545,"path":546,"stem":547,"children":548},"Router Tags and OpenAPI Grouping in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Frouter-tags-and-openapi-grouping","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Frouter-tags-and-openapi-grouping\u002Findex",[549],{"title":545,"path":546,"stem":547},{"title":551,"path":552,"stem":553,"children":554},"Versioning APIs with FastAPI Routers","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization\u002Fversioning-apis-with-routers","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Fversioning-apis-with-routers\u002Findex",[555],{"title":551,"path":552,"stem":553},{"title":557,"path":558,"stem":559,"children":560},"The FastAPI Request\u002FResponse Lifecycle","\u002Fcore-architecture-routing-patterns\u002Frequest-response-lifecycle","core-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Findex",[561,562,568,574],{"title":557,"path":558,"stem":559},{"title":563,"path":564,"stem":565,"children":566},"How a Request Flows Through FastAPI","\u002Fcore-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fhow-a-request-flows-through-fastapi","core-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fhow-a-request-flows-through-fastapi\u002Findex",[567],{"title":563,"path":564,"stem":565},{"title":569,"path":570,"stem":571,"children":572},"Response Model and Serialization Order","\u002Fcore-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fresponse-model-and-serialization-order","core-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fresponse-model-and-serialization-order\u002Findex",[573],{"title":569,"path":570,"stem":571},{"title":575,"path":576,"stem":577,"children":578},"Streaming and File Responses in FastAPI","\u002Fcore-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fstreaming-and-file-responses","core-architecture-routing-patterns\u002Frequest-response-lifecycle\u002Fstreaming-and-file-responses\u002Findex",[579],{"title":575,"path":576,"stem":577},{"id":581,"title":97,"body":582,"dateModified":1664,"datePublished":1664,"description":1665,"extension":1666,"faq":1667,"howto":1678,"meta":1679,"navigation":895,"path":98,"seo":1692,"stem":99,"type":1693,"__hash__":1694},"content\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fmodel-construct-when-to-skip-validation\u002Findex.md",{"type":583,"value":584,"toc":1652},"minimark",[585,589,596,627,636,641,644,649,762,766,781,803,821,836,840,843,1228,1239,1246,1283,1294,1300,1306,1309,1314,1317,1323,1344,1348,1354,1375,1379,1385,1428,1436,1439,1481,1491,1495,1501,1510,1524,1539,1553,1557,1563,1569,1591,1600,1606,1610,1648],[586,587,97],"h1",{"id":588},"model_construct-and-when-to-skip-validation-in-pydantic",[590,591,592],"p",{},[593,594,595],"strong",{},"Key takeaways:",[597,598,599,607,614,621,624],"ul",{},[600,601,602,606],"li",{},[603,604,605],"code",{},"model_construct()"," skips coercion, constraints and every validator; only defaults are applied.",[600,608,609,610,613],{},"Invalid data passes through silently and the result is still an ",[603,611,612],{},"isinstance"," of the model.",[600,615,616,617,620],{},"Omitting a required field produces an object that raises ",[603,618,619],{},"AttributeError"," when you touch it.",[600,622,623],{},"Serializing bad data warns rather than raises, so the corruption travels downstream.",[600,625,626],{},"Use it only for provably-trusted data in a path you have measured.",[590,628,629,630,635],{},"This guide sits under ",[631,632,634],"a",{"href":633},"\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002F","Performance Optimization for Models",", and it is the one page in that topic that is mostly a warning.",[637,638,640],"h2",{"id":639},"the-problem-this-solves","The Problem This Solves",[590,642,643],{},"You are loading fifty thousand rows out of a database into Pydantic models for a report. The rows came from a table whose columns mirror the model exactly, and were written by the same application that defines the model. Revalidating every field is provably redundant work, and a profile confirms it is a real fraction of the request.",[590,645,646,648],{},[603,647,605],{}," is the escape hatch. It builds the model without running any of the validation machinery. And it will do that whether or not your assumption about the data holds — which is the part that has to be understood before it is used, because Pydantic will not tell you when the assumption breaks.",[650,651,657,661,665,672,677,687,692,695,699,702,706,709,713,721,725,728,730,733,735,738,740,745,747,753,758],"svg",{"viewBox":652,"role":653,"ariaLabel":654,"xmlns":655,"style":656},"0 0 720 300","img","What model_validate checks compared with what model_construct skips","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;height:auto;max-width:720px;margin:2rem 0",[658,659,660],"title",{},"model_validate versus model_construct",[662,663,664],"desc",{},"model_validate coerces types, checks constraints, runs validators and applies defaults. model_construct assigns attributes and applies defaults only, skipping coercion and validators entirely. Both return an object that passes an isinstance check.",[666,667,671],"text",{"x":668,"y":669,"style":670},"180","26","text-anchor:middle;fill:#00796B;font:700 13px sans-serif","model_validate",[666,673,676],{"x":674,"y":669,"style":675},"540","text-anchor:middle;fill:currentColor;font:700 13px sans-serif","model_construct",[678,679],"rect",{"x":680,"y":680,"width":681,"height":682,"rx":683,"fill":684,"stroke":685,"strokeWidth":686},"40","280","34","7","none","#00796B","2",[666,688,691],{"x":668,"y":689,"style":690},"62","text-anchor:middle;fill:#00796B;font:400 12px sans-serif","coerce types",[678,693],{"x":680,"y":694,"width":681,"height":682,"rx":683,"fill":684,"stroke":685,"strokeWidth":686},"84",[666,696,698],{"x":668,"y":697,"style":690},"106","check field constraints",[678,700],{"x":680,"y":701,"width":681,"height":682,"rx":683,"fill":684,"stroke":685,"strokeWidth":686},"128",[666,703,705],{"x":668,"y":704,"style":690},"150","run field and model validators",[678,707],{"x":680,"y":708,"width":681,"height":682,"rx":683,"fill":684,"stroke":685,"strokeWidth":686},"172",[666,710,712],{"x":668,"y":711,"style":690},"194","apply defaults",[678,714],{"x":715,"y":680,"width":681,"height":682,"rx":683,"fill":684,"stroke":716,"strokeWidth":717,"strokeDashArray":718},"400","currentColor","1.2",[719,720],"5","4",[666,722,724],{"x":674,"y":689,"style":723},"text-anchor:middle;fill:currentColor;font:400 12px sans-serif","skipped",[678,726],{"x":715,"y":694,"width":681,"height":682,"rx":683,"fill":684,"stroke":716,"strokeWidth":717,"strokeDashArray":727},[719,720],[666,729,724],{"x":674,"y":697,"style":723},[678,731],{"x":715,"y":701,"width":681,"height":682,"rx":683,"fill":684,"stroke":716,"strokeWidth":717,"strokeDashArray":732},[719,720],[666,734,724],{"x":674,"y":704,"style":723},[678,736],{"x":715,"y":708,"width":681,"height":682,"rx":683,"fill":684,"stroke":716,"strokeWidth":737},"1.5",[666,739,712],{"x":674,"y":711,"style":723},[741,742],"line",{"x1":668,"y1":743,"x2":668,"y2":744,"stroke":685,"strokeWidth":737},"206","230",[741,746],{"x1":674,"y1":743,"x2":674,"y2":744,"stroke":716,"strokeWidth":737},[678,748],{"x":668,"y":749,"width":750,"height":751,"rx":752,"fill":684,"stroke":685,"strokeWidth":686},"232","360","42","8",[666,754,757],{"x":750,"y":755,"style":756},"258","text-anchor:middle;fill:#00796B;font:600 12px sans-serif","an Account instance either way",[666,759,761],{"x":750,"y":760,"style":723},"294","Nothing downstream can tell which path produced it.",[637,763,765],{"id":764},"why-it-happens","Why It Happens",[590,767,768,769,772,773,776,777,780],{},"A ",[603,770,771],{},"BaseModel"," instance is, underneath, a ",[603,774,775],{},"__dict__"," of field values plus a ",[603,778,779],{},"__pydantic_fields_set__"," set recording which fields were explicitly supplied. Validation is not a property of the instance; it is a step that happens on the way in.",[590,782,783,785,786,789,790,793,794,796,797,799,800,802],{},[603,784,671],{}," runs the compiled core validator: coerce each value to its annotated type, enforce constraints, run ",[603,787,788],{},"field_validator"," and ",[603,791,792],{},"model_validator"," functions, fill defaults, and only then populate ",[603,795,775],{},". ",[603,798,676],{}," writes to ",[603,801,775],{}," directly. It walks the model's fields to fill defaults for anything you omitted, records the fields you did pass, and returns.",[590,804,805,806,809,810,813,814,817,818,820],{},"Because validation was never an instance property, nothing about the resulting object records which route it took. ",[603,807,808],{},"isinstance(obj, Account)"," is ",[603,811,812],{},"True",". Type checkers see an ",[603,815,816],{},"Account",". Every function downstream that accepts an ",[603,819,816],{}," accepts it. The type annotation has become a claim nobody checked.",[590,822,823,824,827,828,831,832,835],{},"Serialization does notice, but only just. Pydantic's serializer is compiled from the same schema, so when it meets a ",[603,825,826],{},"str"," where the schema promised an ",[603,829,830],{},"int"," it emits a ",[603,833,834],{},"PydanticSerializationUnexpectedValue"," warning — and then serializes the value anyway. A warning, in a codebase that has almost certainly configured its warning filters for something else, on a code path that then sends the result to a client.",[637,837,839],{"id":838},"the-fix","The Fix",[590,841,842],{},"There is no fix, in the sense of making this safe. What follows is a demonstration of exactly what gets through, so the decision to use it can be made with the facts.",[844,845,850],"pre",{"className":846,"code":847,"language":848,"meta":849,"style":849},"language-python shiki shiki-themes github-light-high-contrast","\"\"\"Show exactly what model_construct() lets through: no coercion, no constraints, no validators.\"\"\"\nfrom datetime import datetime\nfrom typing import Any\n\nfrom pydantic import BaseModel, Field, ValidationError, field_validator\n\n\nclass Account(BaseModel):\n    id: int\n    email: str = Field(pattern=r\"^[^@]+@[^@]+$\")\n    balance_cents: int = Field(ge=0)\n    created_at: datetime\n    tier: str = \"free\"\n\n    @field_validator(\"email\")\n    @classmethod\n    def lowercase(cls, v: str) -> str:\n        return v.lower()\n\n\n# The same shape as a real row, but wrong in every way a constraint would normally catch.\nPOISONED_ROW: dict[str, Any] = {\n    \"id\": \"not-an-int\",\n    \"email\": \"NOT AN EMAIL AT ALL\",\n    \"balance_cents\": -9999,\n    \"created_at\": \"definitely not a datetime\",\n    \"tier\": [\"unexpected\", \"list\"],\n}\n","python","",[603,851,852,860,877,890,897,910,915,920,939,951,1009,1031,1037,1050,1055,1069,1078,1100,1109,1114,1119,1126,1145,1159,1172,1188,1201,1222],{"__ignoreMap":849},[853,854,856],"span",{"class":741,"line":855},1,[853,857,859],{"class":858},"sYEJz","\"\"\"Show exactly what model_construct() lets through: no coercion, no constraints, no validators.\"\"\"\n",[853,861,863,867,871,874],{"class":741,"line":862},2,[853,864,866],{"class":865},"sTJeM","from",[853,868,870],{"class":869},"sigWx"," datetime ",[853,872,873],{"class":865},"import",[853,875,876],{"class":869}," datetime\n",[853,878,880,882,885,887],{"class":741,"line":879},3,[853,881,866],{"class":865},[853,883,884],{"class":869}," typing ",[853,886,873],{"class":865},[853,888,889],{"class":869}," Any\n",[853,891,893],{"class":741,"line":892},4,[853,894,896],{"emptyLinePlaceholder":895},true,"\n",[853,898,900,902,905,907],{"class":741,"line":899},5,[853,901,866],{"class":865},[853,903,904],{"class":869}," pydantic ",[853,906,873],{"class":865},[853,908,909],{"class":869}," BaseModel, Field, ValidationError, field_validator\n",[853,911,913],{"class":741,"line":912},6,[853,914,896],{"emptyLinePlaceholder":895},[853,916,918],{"class":741,"line":917},7,[853,919,896],{"emptyLinePlaceholder":895},[853,921,923,926,930,933,936],{"class":741,"line":922},8,[853,924,925],{"class":865},"class",[853,927,929],{"class":928},"sV4o_"," Account",[853,931,932],{"class":869},"(",[853,934,771],{"class":935},"sacAq",[853,937,938],{"class":869},"):\n",[853,940,942,945,948],{"class":741,"line":941},9,[853,943,944],{"class":935},"    id",[853,946,947],{"class":869},": ",[853,949,950],{"class":935},"int\n",[853,952,954,957,959,962,965,968,971,974,977,980,983,986,989,992,995,997,999,1001,1004,1006],{"class":741,"line":953},10,[853,955,956],{"class":869},"    email: ",[853,958,826],{"class":935},[853,960,961],{"class":865}," =",[853,963,964],{"class":869}," Field(",[853,966,967],{"class":928},"pattern",[853,969,970],{"class":865},"=",[853,972,973],{"class":865},"r",[853,975,976],{"class":858},"\"",[853,978,979],{"class":935},"^[",[853,981,982],{"class":865},"^@",[853,984,985],{"class":935},"]",[853,987,988],{"class":865},"+",[853,990,991],{"class":858},"@",[853,993,994],{"class":935},"[",[853,996,982],{"class":865},[853,998,985],{"class":935},[853,1000,988],{"class":865},[853,1002,1003],{"class":935},"$",[853,1005,976],{"class":858},[853,1007,1008],{"class":869},")\n",[853,1010,1012,1015,1017,1019,1021,1024,1026,1029],{"class":741,"line":1011},11,[853,1013,1014],{"class":869},"    balance_cents: ",[853,1016,830],{"class":935},[853,1018,961],{"class":865},[853,1020,964],{"class":869},[853,1022,1023],{"class":928},"ge",[853,1025,970],{"class":865},[853,1027,1028],{"class":935},"0",[853,1030,1008],{"class":869},[853,1032,1034],{"class":741,"line":1033},12,[853,1035,1036],{"class":869},"    created_at: datetime\n",[853,1038,1040,1043,1045,1047],{"class":741,"line":1039},13,[853,1041,1042],{"class":869},"    tier: ",[853,1044,826],{"class":935},[853,1046,961],{"class":865},[853,1048,1049],{"class":858}," \"free\"\n",[853,1051,1053],{"class":741,"line":1052},14,[853,1054,896],{"emptyLinePlaceholder":895},[853,1056,1058,1062,1064,1067],{"class":741,"line":1057},15,[853,1059,1061],{"class":1060},"s3dhs","    @field_validator",[853,1063,932],{"class":869},[853,1065,1066],{"class":858},"\"email\"",[853,1068,1008],{"class":869},[853,1070,1072,1075],{"class":741,"line":1071},16,[853,1073,1074],{"class":1060},"    @",[853,1076,1077],{"class":935},"classmethod\n",[853,1079,1081,1084,1087,1090,1092,1095,1097],{"class":741,"line":1080},17,[853,1082,1083],{"class":865},"    def",[853,1085,1086],{"class":1060}," lowercase",[853,1088,1089],{"class":869},"(cls, v: ",[853,1091,826],{"class":935},[853,1093,1094],{"class":869},") -> ",[853,1096,826],{"class":935},[853,1098,1099],{"class":869},":\n",[853,1101,1103,1106],{"class":741,"line":1102},18,[853,1104,1105],{"class":865},"        return",[853,1107,1108],{"class":869}," v.lower()\n",[853,1110,1112],{"class":741,"line":1111},19,[853,1113,896],{"emptyLinePlaceholder":895},[853,1115,1117],{"class":741,"line":1116},20,[853,1118,896],{"emptyLinePlaceholder":895},[853,1120,1122],{"class":741,"line":1121},21,[853,1123,1125],{"class":1124},"sFeEa","# The same shape as a real row, but wrong in every way a constraint would normally catch.\n",[853,1127,1129,1132,1135,1137,1140,1142],{"class":741,"line":1128},22,[853,1130,1131],{"class":935},"POISONED_ROW",[853,1133,1134],{"class":869},": dict[",[853,1136,826],{"class":935},[853,1138,1139],{"class":869},", Any] ",[853,1141,970],{"class":865},[853,1143,1144],{"class":869}," {\n",[853,1146,1148,1151,1153,1156],{"class":741,"line":1147},23,[853,1149,1150],{"class":858},"    \"id\"",[853,1152,947],{"class":869},[853,1154,1155],{"class":858},"\"not-an-int\"",[853,1157,1158],{"class":869},",\n",[853,1160,1162,1165,1167,1170],{"class":741,"line":1161},24,[853,1163,1164],{"class":858},"    \"email\"",[853,1166,947],{"class":869},[853,1168,1169],{"class":858},"\"NOT AN EMAIL AT ALL\"",[853,1171,1158],{"class":869},[853,1173,1175,1178,1180,1183,1186],{"class":741,"line":1174},25,[853,1176,1177],{"class":858},"    \"balance_cents\"",[853,1179,947],{"class":869},[853,1181,1182],{"class":865},"-",[853,1184,1185],{"class":935},"9999",[853,1187,1158],{"class":869},[853,1189,1191,1194,1196,1199],{"class":741,"line":1190},26,[853,1192,1193],{"class":858},"    \"created_at\"",[853,1195,947],{"class":869},[853,1197,1198],{"class":858},"\"definitely not a datetime\"",[853,1200,1158],{"class":869},[853,1202,1204,1207,1210,1213,1216,1219],{"class":741,"line":1203},27,[853,1205,1206],{"class":858},"    \"tier\"",[853,1208,1209],{"class":869},": [",[853,1211,1212],{"class":858},"\"unexpected\"",[853,1214,1215],{"class":869},", ",[853,1217,1218],{"class":858},"\"list\"",[853,1220,1221],{"class":869},"],\n",[853,1223,1225],{"class":741,"line":1224},28,[853,1226,1227],{"class":869},"}\n",[590,1229,1230,1231,1234,1235,1238],{},"That dictionary violates the type of every field, a regex pattern, a ",[603,1232,1233],{},"ge=0"," constraint, and would have been lowercased by a validator. Here is what ",[603,1236,1237],{},"Account.model_construct(**POISONED_ROW)"," produces. Real output:",[844,1240,1244],{"className":1241,"code":1243,"language":666,"meta":849},[1242],"language-text","$ GET \u002Fpoisoned\n200 OK\n{\n  \"id\": \"not-an-int\",\n  \"id_python_type\": \"str\",\n  \"email\": \"NOT AN EMAIL AT ALL\",\n  \"email_validator_ran\": false,\n  \"balance_cents\": -9999,\n  \"tier\": [\n    \"unexpected\",\n    \"list\"\n  ],\n  \"created_at_python_type\": \"str\",\n  \"isinstance_of_Account\": true,\n  \"serialization\": {\n    \"dumped\": {\n      \"id\": \"not-an-int\",\n      \"email\": \"NOT AN EMAIL AT ALL\",\n      \"balance_cents\": -9999,\n      \"created_at\": \"definitely not a datetime\",\n      \"tier\": [\n        \"unexpected\",\n        \"list\"\n      ]\n    },\n    \"warnings\": [\n      \"Pydantic serializer warnings:\",\n      \"  PydanticSerializationUnexpectedValue(Expected `int` - serialized value may not be as expected [field_name='id', input_value='not-an-int', input_type=str])\",\n      \"  PydanticSerializationUnexpectedValue(Expected `datetime` - serialized value may not be as expected [field_name='created_at', input_value='definitely not a datetime', input_type=str])\",\n      \"  PydanticSerializationUnexpectedValue(Expected `str` - serialized value may not be as expected [field_name='tier', input_value=['unexpected', 'list'], input_type=list])\"\n    ]\n  }\n}\n",[603,1245,1243],{"__ignoreMap":849},[590,1247,1248,1249,1252,1253,1255,1256,796,1258,1261,1262,1264,1265,1268,1269,1272,1273,1275,1276,809,1279,1282],{},"No exception. Status 200. ",[603,1250,1251],{},"account.id"," is the string ",[603,1254,1155],{}," on a field annotated ",[603,1257,830],{},[603,1259,1260],{},"balance_cents"," is negative despite ",[603,1263,1233],{},". The ",[603,1266,1267],{},"email"," validator did not run, so the value is still upper case. ",[603,1270,1271],{},"tier"," is a list on a ",[603,1274,826],{}," field. And ",[603,1277,1278],{},"isinstance_of_Account",[603,1280,1281],{},"true",", so nothing downstream — no type checker, no runtime check, no function signature — will notice.",[590,1284,1285,1286,1289,1290,1293],{},"The ",[603,1287,1288],{},"dumped"," block is the part that should decide the question. ",[603,1291,1292],{},"model_dump(mode=\"json\")"," produced a JSON-shaped dictionary containing every bad value. The three warnings were captured here deliberately; in a normal process they go wherever your warning configuration sends them, which for most services is nowhere. Return that from an endpoint and you have served a response that violates your own published schema, with a 200 status code.",[590,1295,1296,1297,1299],{},"For contrast, the same dictionary through ",[603,1298,671],{},":",[844,1301,1304],{"className":1302,"code":1303,"language":666,"meta":849},[1242],"$ GET \u002Fcompare\n200 OK\n{\n  \"model_validate_raised\": 5,\n  \"errors\": [\n    {\n      \"loc\": [\n        \"id\"\n      ],\n      \"type\": \"int_parsing\",\n      \"msg\": \"Input should be a valid integer, unable to parse string as an integer\"\n    },\n    {\n      \"loc\": [\n        \"email\"\n      ],\n      \"type\": \"string_pattern_mismatch\",\n      \"msg\": \"String should match pattern '^[^@]+@[^@]+$'\"\n    },\n    {\n      \"loc\": [\n        \"balance_cents\"\n      ],\n      \"type\": \"greater_than_equal\",\n      \"msg\": \"Input should be greater than or equal to 0\"\n    },\n    {\n      \"loc\": [\n        \"created_at\"\n      ],\n      \"type\": \"datetime_from_date_parsing\",\n      \"msg\": \"Input should be a valid datetime or date, invalid character in year\"\n    },\n    {\n      \"loc\": [\n        \"tier\"\n      ],\n      \"type\": \"string_type\",\n      \"msg\": \"Input should be a valid string\"\n    }\n  ]\n}\n",[603,1305,1303],{"__ignoreMap":849},[590,1307,1308],{},"Five errors, one per field. That is the difference the two method names hide: identical input, identical model, and one path reports every problem while the other reports none.",[1310,1311,1313],"h3",{"id":1312},"missing-fields-are-worse-than-wrong-ones","Missing fields are worse than wrong ones",[590,1315,1316],{},"Wrong values at least exist. Omitted required fields produce an object that is not merely wrong but structurally incomplete:",[844,1318,1321],{"className":1319,"code":1320,"language":666,"meta":849},[1242],"$ GET \u002Fmissing-field\n200 OK\n{\n  \"constructed_without_balance_or_created_at\": true,\n  \"tier\": \"free\",\n  \"has_balance_cents_attribute\": false,\n  \"attribute_error_on_access\": \"AttributeError: 'Account' object has no attribute 'balance_cents'\"\n}\n",[603,1322,1320],{"__ignoreMap":849},[590,1324,1325,1328,1329,1331,1332,1334,1335,789,1337,1340,1341,1343],{},[603,1326,1327],{},"Account.model_construct(id=2, email=\"grace@example.com\")"," returned happily. The ",[603,1330,1271],{}," default was applied, because defaults are the one thing ",[603,1333,676],{}," does. But ",[603,1336,1260],{},[603,1338,1339],{},"created_at"," simply are not there, and the failure surfaces as a bare ",[603,1342,619],{}," at whatever unrelated point in your code first reads the field — a stack trace with no connection to the line that built the object.",[1310,1345,1347],{"id":1346},"the-narrow-case-where-it-is-fine","The narrow case where it is fine",[844,1349,1352],{"className":1350,"code":1351,"language":666,"meta":849},[1242],"$ GET \u002Ftrusted\n200 OK\n{\n  \"id\": 1,\n  \"email\": \"ada@example.com\",\n  \"tier_default_applied\": \"free\",\n  \"fields_set\": [\n    \"balance_cents\",\n    \"created_at\",\n    \"email\",\n    \"id\"\n  ]\n}\n",[603,1353,1351],{"__ignoreMap":849},[590,1355,1356,1357,1359,1360,1363,1364,1367,1368,1370,1371,1374],{},"This is the intended use: every field present, every type already correct — ",[603,1358,1339],{}," was a real ",[603,1361,1362],{},"datetime"," object, not a string — and no coercion needed because the source system produces the right types. Note ",[603,1365,1366],{},"fields_set"," lists the four fields that were passed and not ",[603,1369,1271],{},", which came from its default. That set is what drives ",[603,1372,1373],{},"exclude_unset",", and it is tracked correctly, so a constructed model still serializes with the same include and exclude semantics as a validated one.",[637,1376,1378],{"id":1377},"verification","Verification",[590,1380,1381,1382,1384],{},"If you use ",[603,1383,676],{}," at all, make the assumption it rests on into a test. Validate the trusted source once, in CI, against real data:",[844,1386,1388],{"className":846,"code":1387,"language":848,"meta":849,"style":849},"def test_database_rows_would_pass_validation(sample_rows):\n    \"\"\"The premise of using model_construct on this query, asserted.\"\"\"\n    for row in sample_rows:\n        Account.model_validate(row)      # must never raise\n",[603,1389,1390,1401,1406,1420],{"__ignoreMap":849},[853,1391,1392,1395,1398],{"class":741,"line":855},[853,1393,1394],{"class":865},"def",[853,1396,1397],{"class":1060}," test_database_rows_would_pass_validation",[853,1399,1400],{"class":869},"(sample_rows):\n",[853,1402,1403],{"class":741,"line":862},[853,1404,1405],{"class":858},"    \"\"\"The premise of using model_construct on this query, asserted.\"\"\"\n",[853,1407,1408,1411,1414,1417],{"class":741,"line":879},[853,1409,1410],{"class":865},"    for",[853,1412,1413],{"class":869}," row ",[853,1415,1416],{"class":865},"in",[853,1418,1419],{"class":869}," sample_rows:\n",[853,1421,1422,1425],{"class":741,"line":892},[853,1423,1424],{"class":869},"        Account.model_validate(row)      ",[853,1426,1427],{"class":1124},"# must never raise\n",[590,1429,1430,1431,1435],{},"That test is the entire safety argument. It says the fast path is safe ",[1432,1433,1434],"em",{},"because"," the slow path succeeds on the same shape. When a migration changes a column type, this fails in CI instead of silently producing wrong objects in production.",[590,1437,1438],{},"Second, turn the serializer warning into something you would actually notice, at least in tests:",[844,1440,1442],{"className":846,"code":1441,"language":848,"meta":849,"style":849},"def test_constructed_models_serialize_cleanly():\n    with warnings.catch_warnings():\n        warnings.simplefilter(\"error\")   # promote the warning to an exception\n        build_report_rows()\n",[603,1443,1444,1454,1462,1476],{"__ignoreMap":849},[853,1445,1446,1448,1451],{"class":741,"line":855},[853,1447,1394],{"class":865},[853,1449,1450],{"class":1060}," test_constructed_models_serialize_cleanly",[853,1452,1453],{"class":869},"():\n",[853,1455,1456,1459],{"class":741,"line":862},[853,1457,1458],{"class":865},"    with",[853,1460,1461],{"class":869}," warnings.catch_warnings():\n",[853,1463,1464,1467,1470,1473],{"class":741,"line":879},[853,1465,1466],{"class":869},"        warnings.simplefilter(",[853,1468,1469],{"class":858},"\"error\"",[853,1471,1472],{"class":869},")   ",[853,1474,1475],{"class":1124},"# promote the warning to an exception\n",[853,1477,1478],{"class":741,"line":892},[853,1479,1480],{"class":869},"        build_report_rows()\n",[590,1482,1483,1484,1487,1488,1490],{},"Third, make the usage greppable. Wrap it in one function with a name that says what it assumes — ",[603,1485,1486],{},"from_trusted_row"," rather than a bare ",[603,1489,676],{}," call scattered across the codebase — so a reviewer can see every site at once and a newcomer cannot copy the idiom by accident.",[637,1492,1494],{"id":1493},"trade-offs-and-when-not-to","Trade-offs and When Not To",[590,1496,1497,1500],{},[593,1498,1499],{},"Never on anything that crossed a boundary."," Request bodies, webhook payloads, queue messages, third-party API responses, files, and anything a user could influence. Validation is the boundary. Skipping it there does not make the code faster in any way that matters; it removes the reason the model exists.",[590,1502,1503,1506,1507,1509],{},[593,1504,1505],{},"Cache entries are not trusted data."," A serialized model in Redis was written by a previous deploy, with a previous version of the model. That is a schema-migration problem wearing a trusted-data costume, and it is one of the more common ways ",[603,1508,676],{}," causes an incident.",[590,1511,1512,1515,1516,1518,1519,1523],{},[593,1513,1514],{},"Measure before, not after."," In an ordinary endpoint the time goes to database round trips, serialization and network, not to validation. ",[603,1517,676],{}," is worth considering when a profile shows validation itself is significant — bulk loads, batch jobs, large report queries — and is otherwise a risk taken for no measured gain. If the pressure is on serialization rather than validation, ",[631,1520,1522],{"href":1521},"\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance\u002F","Pydantic Model Serialization Performance"," is the more useful page.",[590,1525,1526,1529,1530,1534,1535,1538],{},[593,1527,1528],{},"Consider the alternatives first."," Fetching fewer columns, avoiding the model entirely for a bulk path, or using a ",[631,1531,1533],{"href":1532},"\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Ftypeadapter-for-non-model-types\u002F","TypeAdapter"," over a ",[603,1536,1537],{},"list[Model]"," — which validates the whole batch in one Rust pass rather than looping in Python — all reduce cost without giving up correctness. Exhaust those before giving up the guarantees.",[590,1540,1541,1544,1545,1548,1549,1552],{},[593,1542,1543],{},"Response models re-validate anyway."," If a constructed object is returned from a route with a ",[603,1546,1547],{},"response_model",", FastAPI validates it on the way out, so you have paid the cost you were avoiding ",[1432,1550,1551],{},"and"," moved the failure to a place that produces a 500 rather than a clear error. The optimisation only pays inside code that never crosses the response boundary.",[637,1554,1556],{"id":1555},"faq","FAQ",[590,1558,1559,1562],{},[593,1560,1561],{},"What exactly does model_construct skip?","\nEverything except default application. No type coercion, no field constraints, no field or model validators, and no check that required fields are present. It sets the attributes you pass, fills defaults for fields you omit, and returns.",[590,1564,1565,1568],{},[593,1566,1567],{},"Is model_construct actually faster?","\nIt does strictly less work, so yes, but the saving is per-object and only matters when you are building very many objects from data you have already validated. Profile before reaching for it — in most endpoints serialization and I\u002FO dominate, not validation.",[590,1570,1571,1574,1575,1577,1578,1215,1580,1583,1584,1587,1588,1590],{},[593,1572,1573],{},"What happens if I omit a required field?","\nNothing, until you touch it. A real run constructed an ",[603,1576,816],{}," without ",[603,1579,1260],{},[603,1581,1582],{},"hasattr"," returned ",[603,1585,1586],{},"False",", and reading the attribute raised ",[603,1589,619],{}," rather than any Pydantic error. The object is silently incomplete.",[590,1592,1593,1596,1597,1599],{},[593,1594,1595],{},"Will serialization catch the bad data?","\nOnly as a warning. Dumping a model built from wrong types emits ",[603,1598,834],{}," warnings and still produces output containing the bad values, so a warning filter set to ignore turns it into silent corruption downstream.",[590,1601,1602,1605],{},[593,1603,1604],{},"When is skipping validation genuinely safe?","\nWhen the data provably cannot be wrong and you are in a measured hot path — rows from a database whose schema mirrors the model, or objects your own code validated moments earlier. Never for anything that crossed a network or a user boundary.",[637,1607,1609],{"id":1608},"related-reading","Related Reading",[597,1611,1612,1621,1627,1632,1641],{},[600,1613,1614,1617,1618,1620],{},[593,1615,1616],{},"Up to the topic:"," ",[631,1619,634],{"href":633},".",[600,1622,1623,1624,1620],{},"Validate a whole batch in one pass instead of skipping validation: ",[631,1625,1626],{"href":1532},"TypeAdapter for Non-Model Types",[600,1628,1629,1630,1620],{},"Where the time usually actually goes: ",[631,1631,1522],{"href":1521},[600,1633,1634,1635,1637,1638,1620],{},"The validators ",[603,1636,676],{}," silently skips: ",[631,1639,25],{"href":1640},"\u002Fadvanced-pydantic-validation-serialization\u002Fcustom-validators-field-constraints\u002Fcreating-reusable-custom-validators-in-pydantic\u002F",[600,1642,1643,1644,1620],{},"Loading rows efficiently in the first place: ",[631,1645,1647],{"href":1646},"\u002Fasync-background-tasks-observability\u002Fasync-database-sessions\u002Fasync-sqlalchemy-session-per-request\u002F","Async SQLAlchemy Session Per Request",[1649,1650,1651],"style",{},"html pre.shiki code .sYEJz, html code.shiki .sYEJz{--shiki-default:#032563}html pre.shiki code .sTJeM, html code.shiki .sTJeM{--shiki-default:#A0111F}html pre.shiki code .sigWx, html code.shiki .sigWx{--shiki-default:#0E1116}html pre.shiki code .sV4o_, html code.shiki .sV4o_{--shiki-default:#702C00}html pre.shiki code .sacAq, html code.shiki .sacAq{--shiki-default:#023B95}html pre.shiki code .s3dhs, html code.shiki .s3dhs{--shiki-default:#622CBC}html pre.shiki code .sFeEa, html code.shiki .sFeEa{--shiki-default:#66707B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":849,"searchDepth":862,"depth":862,"links":1653},[1654,1655,1656,1660,1661,1662,1663],{"id":639,"depth":862,"text":640},{"id":764,"depth":862,"text":765},{"id":838,"depth":862,"text":839,"children":1657},[1658,1659],{"id":1312,"depth":879,"text":1313},{"id":1346,"depth":879,"text":1347},{"id":1377,"depth":862,"text":1378},{"id":1493,"depth":862,"text":1494},{"id":1555,"depth":862,"text":1556},{"id":1608,"depth":862,"text":1609},"2026-07-20","What Pydantic's model_construct() actually skips — coercion, constraints and validators — proven with real output, plus the narrow cases where skipping is safe.","md",[1668,1670,1672,1674,1676],{"q":1561,"a":1669},"Everything except default application. No type coercion, no field constraints, no field or model validators, and no check that required fields are present. It sets the attributes you pass, fills defaults for fields you omit, and returns.",{"q":1567,"a":1671},"It does strictly less work, so yes, but the saving is per-object and only matters when you are building very many objects from data you have already validated. Profile before reaching for it — in most endpoints serialization and I\u002FO dominate, not validation.",{"q":1573,"a":1673},"Nothing, until you touch it. A real run constructed an Account without balance_cents, hasattr returned False, and reading the attribute raised AttributeError rather than any Pydantic error. The object is silently incomplete.",{"q":1595,"a":1675},"Only as a warning. Dumping a model built from wrong types emits PydanticSerializationUnexpectedValue warnings and still produces output containing the bad values, so a warning filter set to ignore turns it into silent corruption downstream.",{"q":1604,"a":1677},"When the data provably cannot be wrong and you are in a measured hot path — rows from a database whose schema mirrors the model, or objects your own code validated moments earlier. Never for anything that crossed a network or a user boundary.",null,{"slug":1680,"breadcrumb":1681},"model-construct-when-to-skip-validation",[1682,1685,1688,1689],{"label":1683,"path":1684},"Home","\u002F",{"label":1686,"path":1687},"Advanced Pydantic Validation & Serialization","\u002Fadvanced-pydantic-validation-serialization\u002F",{"label":634,"path":633},{"label":1690,"path":1691},"model_construct and When to Skip Validation","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fmodel-construct-when-to-skip-validation\u002F",{"title":97,"description":1665},"article","5wyPibeJanuoRyt1SMdzs_Ib0RgA3IeC2FO6otQVXvU",[1678,1678],1784588202620]