[{"data":1,"prerenderedAt":941},["ShallowReactive",2],{"nav":3,"page-\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance\u002F":310,"surround-\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance\u002F":939},[4,96,212],{"title":5,"path":6,"stem":7,"children":8},"Advanced Pydantic Validation Serialization","\u002Fadvanced-pydantic-validation-serialization","advanced-pydantic-validation-serialization",[9,12,30,42,54,66,90],{"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],{"title":13,"path":14,"stem":15},{"title":19,"path":20,"stem":21,"children":22},"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",[23],{"title":19,"path":20,"stem":21},{"title":25,"path":26,"stem":27,"children":28},"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",[29],{"title":25,"path":26,"stem":27},{"title":31,"path":32,"stem":33,"children":34},"JSON Schema Customization in Pydantic and FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fjson-schema-customization","advanced-pydantic-validation-serialization\u002Fjson-schema-customization\u002Findex",[35,36],{"title":31,"path":32,"stem":33},{"title":37,"path":38,"stem":39,"children":40},"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",[41],{"title":37,"path":38,"stem":39},{"title":43,"path":44,"stem":45,"children":46},"Nested Model Serialization in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization","advanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Findex",[47,48],{"title":43,"path":44,"stem":45},{"title":49,"path":50,"stem":51,"children":52},"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",[53],{"title":49,"path":50,"stem":51},{"title":55,"path":56,"stem":57,"children":58},"Performance Optimization for Pydantic Models in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models","advanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Findex",[59,60],{"title":55,"path":56,"stem":57},{"title":61,"path":62,"stem":63,"children":64},"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",[65],{"title":61,"path":62,"stem":63},{"title":67,"path":68,"stem":69,"children":70},"Pydantic V2 Migration Guide for FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide","advanced-pydantic-validation-serialization\u002Fpydantic-v2-migration-guide\u002Findex",[71,72,78,84],{"title":67,"path":68,"stem":69},{"title":73,"path":74,"stem":75,"children":76},"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",[77],{"title":73,"path":74,"stem":75},{"title":79,"path":80,"stem":81,"children":82},"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",[83],{"title":79,"path":80,"stem":81},{"title":85,"path":86,"stem":87,"children":88},"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",[89],{"title":85,"path":86,"stem":87},{"title":91,"path":92,"stem":93,"children":94},"Type Hinting and IDE Integration in FastAPI","\u002Fadvanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration","advanced-pydantic-validation-serialization\u002Ftype-hinting-ide-integration\u002Findex",[95],{"title":91,"path":92,"stem":93},{"title":97,"path":98,"stem":99,"children":100},"Async Background Tasks Observability","\u002Fasync-background-tasks-observability","async-background-tasks-observability",[101,104,122,140,158,176,194],{"title":102,"path":98,"stem":103},"Async, Background Tasks, and Observability in FastAPI","async-background-tasks-observability\u002Findex",{"title":105,"path":106,"stem":107,"children":108},"Async Correctness and Concurrency in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-correctness-concurrency","async-background-tasks-observability\u002Fasync-correctness-concurrency\u002Findex",[109,110,116],{"title":105,"path":106,"stem":107},{"title":111,"path":112,"stem":113,"children":114},"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",[115],{"title":111,"path":112,"stem":113},{"title":117,"path":118,"stem":119,"children":120},"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",[121],{"title":117,"path":118,"stem":119},{"title":123,"path":124,"stem":125,"children":126},"Async Database Sessions in FastAPI","\u002Fasync-background-tasks-observability\u002Fasync-database-sessions","async-background-tasks-observability\u002Fasync-database-sessions\u002Findex",[127,128,134],{"title":123,"path":124,"stem":125},{"title":129,"path":130,"stem":131,"children":132},"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",[133],{"title":129,"path":130,"stem":131},{"title":135,"path":136,"stem":137,"children":138},"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",[139],{"title":135,"path":136,"stem":137},{"title":141,"path":142,"stem":143,"children":144},"Background Task Processing in FastAPI","\u002Fasync-background-tasks-observability\u002Fbackground-task-processing","async-background-tasks-observability\u002Fbackground-task-processing\u002Findex",[145,146,152],{"title":141,"path":142,"stem":143},{"title":147,"path":148,"stem":149,"children":150},"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",[151],{"title":147,"path":148,"stem":149},{"title":153,"path":154,"stem":155,"children":156},"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",[157],{"title":153,"path":154,"stem":155},{"title":159,"path":160,"stem":161,"children":162},"Caching Strategies in FastAPI","\u002Fasync-background-tasks-observability\u002Fcaching-strategies","async-background-tasks-observability\u002Fcaching-strategies\u002Findex",[163,164,170],{"title":159,"path":160,"stem":161},{"title":165,"path":166,"stem":167,"children":168},"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",[169],{"title":165,"path":166,"stem":167},{"title":171,"path":172,"stem":173,"children":174},"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",[175],{"title":171,"path":172,"stem":173},{"title":177,"path":178,"stem":179,"children":180},"Observability and Tracing in FastAPI","\u002Fasync-background-tasks-observability\u002Fobservability-and-tracing","async-background-tasks-observability\u002Fobservability-and-tracing\u002Findex",[181,182,188],{"title":177,"path":178,"stem":179},{"title":183,"path":184,"stem":185,"children":186},"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",[187],{"title":183,"path":184,"stem":185},{"title":189,"path":190,"stem":191,"children":192},"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",[193],{"title":189,"path":190,"stem":191},{"title":195,"path":196,"stem":197,"children":198},"Rate Limiting and Throttling in FastAPI","\u002Fasync-background-tasks-observability\u002Frate-limiting-throttling","async-background-tasks-observability\u002Frate-limiting-throttling\u002Findex",[199,200,206],{"title":195,"path":196,"stem":197},{"title":201,"path":202,"stem":203,"children":204},"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",[205],{"title":201,"path":202,"stem":203},{"title":207,"path":208,"stem":209,"children":210},"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",[211],{"title":207,"path":208,"stem":209},{"title":213,"path":214,"stem":215,"children":216},"Core Architecture Routing Patterns","\u002Fcore-architecture-routing-patterns","core-architecture-routing-patterns",[217,220,232,250,268,280,292],{"title":218,"path":214,"stem":219},"FastAPI Core Architecture and Routing Patterns","core-architecture-routing-patterns\u002Findex",{"title":221,"path":222,"stem":223,"children":224},"Application Factory Patterns in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fapplication-factory-patterns","core-architecture-routing-patterns\u002Fapplication-factory-patterns\u002Findex",[225,226],{"title":221,"path":222,"stem":223},{"title":227,"path":228,"stem":229,"children":230},"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",[231],{"title":227,"path":228,"stem":229},{"title":233,"path":234,"stem":235,"children":236},"Configuration Management in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fconfiguration-management","core-architecture-routing-patterns\u002Fconfiguration-management\u002Findex",[237,238,244],{"title":233,"path":234,"stem":235},{"title":239,"path":240,"stem":241,"children":242},"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",[243],{"title":239,"path":240,"stem":241},{"title":245,"path":246,"stem":247,"children":248},"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",[249],{"title":245,"path":246,"stem":247},{"title":251,"path":252,"stem":253,"children":254},"Dependency Injection Strategies in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fdependency-injection-strategies","core-architecture-routing-patterns\u002Fdependency-injection-strategies\u002Findex",[255,256,262],{"title":251,"path":252,"stem":253},{"title":257,"path":258,"stem":259,"children":260},"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",[261],{"title":257,"path":258,"stem":259},{"title":263,"path":264,"stem":265,"children":266},"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",[267],{"title":263,"path":264,"stem":265},{"title":269,"path":270,"stem":271,"children":272},"Error Handling and Global Exceptions in FastAPI","\u002Fcore-architecture-routing-patterns\u002Ferror-handling-global-exceptions","core-architecture-routing-patterns\u002Ferror-handling-global-exceptions\u002Findex",[273,274],{"title":269,"path":270,"stem":271},{"title":275,"path":276,"stem":277,"children":278},"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",[279],{"title":275,"path":276,"stem":277},{"title":281,"path":282,"stem":283,"children":284},"Middleware Implementation in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmiddleware-implementation","core-architecture-routing-patterns\u002Fmiddleware-implementation\u002Findex",[285,286],{"title":281,"path":282,"stem":283},{"title":287,"path":288,"stem":289,"children":290},"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",[291],{"title":287,"path":288,"stem":289},{"title":293,"path":294,"stem":295,"children":296},"Modular Router Organization in FastAPI","\u002Fcore-architecture-routing-patterns\u002Fmodular-router-organization","core-architecture-routing-patterns\u002Fmodular-router-organization\u002Findex",[297,298,304],{"title":293,"path":294,"stem":295},{"title":299,"path":300,"stem":301,"children":302},"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",[303],{"title":299,"path":300,"stem":301},{"title":305,"path":306,"stem":307,"children":308},"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",[309],{"title":305,"path":306,"stem":307},{"id":311,"title":61,"body":312,"description":892,"extension":893,"meta":894,"navigation":426,"path":62,"seo":937,"stem":63,"__hash__":938},"content\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance\u002Findex.md",{"type":313,"value":314,"toc":879},"minimark",[315,319,326,358,370,375,378,382,390,394,399,531,535,569,573,695,699,767,771,798,802,849,853,875],[316,317,61],"h1",{"id":318},"pydantic-model-serialization-performance-in-fastapi",[320,321,322],"p",{},[323,324,325],"strong",{},"Key takeaways:",[327,328,329,333,341,344,351],"ul",{},[330,331,332],"li",{},"Profile a representative payload first so you optimize the real bottleneck.",[330,334,335,336,340],{},"Use ",[337,338,339],"code",{},"model_dump_json"," for single-pass JSON output.",[330,342,343],{},"Return a trimmed response model so you serialize only needed fields.",[330,345,346,347,350],{},"Reuse a ",[337,348,349],{},"TypeAdapter"," for non-model shapes instead of rebuilding it.",[330,352,353,354,357],{},"Avoid re-validation by passing trusted models through or using ",[337,355,356],{},"model_construct",".",[320,359,360,361,366,367,357],{},"This guide is the serialization-focused companion to ",[362,363,365],"a",{"href":364},"\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002F","Performance Optimization for Models"," and complements ",[362,368,49],{"href":369},"\u002Fadvanced-pydantic-validation-serialization\u002Fnested-model-serialization\u002Fhandling-deeply-nested-json-models-efficiently\u002F",[371,372,374],"h2",{"id":373},"the-problem-this-solves","The Problem This Solves",[320,376,377],{},"Serialization quietly becomes a hot-path cost as payloads grow, especially for nested responses returned at high request rates. The good news is that the biggest wins are simple and measurable: emit JSON in one pass, serialize fewer fields, and stop repeating validation.",[371,379,381],{"id":380},"prerequisites","Prerequisites",[327,383,384,387],{},[330,385,386],{},"Pydantic v2 (the Rust core enables single-pass serialization).",[330,388,389],{},"A representative payload and a way to time it.",[371,391,393],{"id":392},"step-by-step-implementation","Step-by-Step Implementation",[395,396,398],"h3",{"id":397},"_1-profile-first","1. Profile first",[400,401,406],"pre",{"className":402,"code":403,"language":404,"meta":405,"style":405},"language-python shiki shiki-themes github-light","import time\n\n\ndef profile_serialize(model, n: int = 1000) -> float:\n    start = time.perf_counter()\n    for _ in range(n):\n        model.model_dump_json()\n    return (time.perf_counter() - start) \u002F n * 1000   # ms per call\n","python","",[337,407,408,421,428,433,465,477,495,501],{"__ignoreMap":405},[409,410,413,417],"span",{"class":411,"line":412},"line",1,[409,414,416],{"class":415},"sD7c4","import",[409,418,420],{"class":419},"sgsFI"," time\n",[409,422,424],{"class":411,"line":423},2,[409,425,427],{"emptyLinePlaceholder":426},true,"\n",[409,429,431],{"class":411,"line":430},3,[409,432,427],{"emptyLinePlaceholder":426},[409,434,436,439,443,446,450,453,456,459,462],{"class":411,"line":435},4,[409,437,438],{"class":415},"def",[409,440,442],{"class":441},"s7eDp"," profile_serialize",[409,444,445],{"class":419},"(model, n: ",[409,447,449],{"class":448},"sYu0t","int",[409,451,452],{"class":415}," =",[409,454,455],{"class":448}," 1000",[409,457,458],{"class":419},") -> ",[409,460,461],{"class":448},"float",[409,463,464],{"class":419},":\n",[409,466,468,471,474],{"class":411,"line":467},5,[409,469,470],{"class":419},"    start ",[409,472,473],{"class":415},"=",[409,475,476],{"class":419}," time.perf_counter()\n",[409,478,480,483,486,489,492],{"class":411,"line":479},6,[409,481,482],{"class":415},"    for",[409,484,485],{"class":419}," _ ",[409,487,488],{"class":415},"in",[409,490,491],{"class":448}," range",[409,493,494],{"class":419},"(n):\n",[409,496,498],{"class":411,"line":497},7,[409,499,500],{"class":419},"        model.model_dump_json()\n",[409,502,504,507,510,513,516,519,522,525,527],{"class":411,"line":503},8,[409,505,506],{"class":415},"    return",[409,508,509],{"class":419}," (time.perf_counter() ",[409,511,512],{"class":415},"-",[409,514,515],{"class":419}," start) ",[409,517,518],{"class":415},"\u002F",[409,520,521],{"class":419}," n ",[409,523,524],{"class":415},"*",[409,526,455],{"class":448},[409,528,530],{"class":529},"sAwPA","   # ms per call\n",[395,532,534],{"id":533},"_2-single-pass-json","2. Single-pass JSON",[400,536,538],{"className":402,"code":537,"language":404,"meta":405,"style":405},"# Efficient: one pass on the Rust core.\nbody = order.model_dump_json()\n\n# Avoid on large graphs: builds a dict, then re-encodes in Python.\n# body = json.dumps(order.model_dump())\n",[337,539,540,545,555,559,564],{"__ignoreMap":405},[409,541,542],{"class":411,"line":412},[409,543,544],{"class":529},"# Efficient: one pass on the Rust core.\n",[409,546,547,550,552],{"class":411,"line":423},[409,548,549],{"class":419},"body ",[409,551,473],{"class":415},[409,553,554],{"class":419}," order.model_dump_json()\n",[409,556,557],{"class":411,"line":430},[409,558,427],{"emptyLinePlaceholder":426},[409,560,561],{"class":411,"line":435},[409,562,563],{"class":529},"# Avoid on large graphs: builds a dict, then re-encodes in Python.\n",[409,565,566],{"class":411,"line":467},[409,567,568],{"class":529},"# body = json.dumps(order.model_dump())\n",[395,570,572],{"id":571},"_3-trim-with-a-response-model","3. Trim with a response model",[400,574,576],{"className":402,"code":575,"language":404,"meta":405,"style":405},"from pydantic import BaseModel\n\n\nclass OrderListItem(BaseModel):\n    id: int\n    total: int          # The list view needs two fields, not the whole order.\n\n\n@router.get(\"\u002Forders\", response_model=list[OrderListItem])\nasync def orders() -> list[OrderListItem]:\n    return await fetch_order_list()\n",[337,577,578,591,595,599,616,627,637,641,645,669,684],{"__ignoreMap":405},[409,579,580,583,586,588],{"class":411,"line":412},[409,581,582],{"class":415},"from",[409,584,585],{"class":419}," pydantic ",[409,587,416],{"class":415},[409,589,590],{"class":419}," BaseModel\n",[409,592,593],{"class":411,"line":423},[409,594,427],{"emptyLinePlaceholder":426},[409,596,597],{"class":411,"line":430},[409,598,427],{"emptyLinePlaceholder":426},[409,600,601,604,607,610,613],{"class":411,"line":435},[409,602,603],{"class":415},"class",[409,605,606],{"class":441}," OrderListItem",[409,608,609],{"class":419},"(",[409,611,612],{"class":441},"BaseModel",[409,614,615],{"class":419},"):\n",[409,617,618,621,624],{"class":411,"line":467},[409,619,620],{"class":448},"    id",[409,622,623],{"class":419},": ",[409,625,626],{"class":448},"int\n",[409,628,629,632,634],{"class":411,"line":479},[409,630,631],{"class":419},"    total: ",[409,633,449],{"class":448},[409,635,636],{"class":529},"          # The list view needs two fields, not the whole order.\n",[409,638,639],{"class":411,"line":497},[409,640,427],{"emptyLinePlaceholder":426},[409,642,643],{"class":411,"line":503},[409,644,427],{"emptyLinePlaceholder":426},[409,646,648,651,653,657,660,664,666],{"class":411,"line":647},9,[409,649,650],{"class":441},"@router.get",[409,652,609],{"class":419},[409,654,656],{"class":655},"sYBdl","\"\u002Forders\"",[409,658,659],{"class":419},", ",[409,661,663],{"class":662},"sqxcx","response_model",[409,665,473],{"class":415},[409,667,668],{"class":419},"list[OrderListItem])\n",[409,670,672,675,678,681],{"class":411,"line":671},10,[409,673,674],{"class":415},"async",[409,676,677],{"class":415}," def",[409,679,680],{"class":441}," orders",[409,682,683],{"class":419},"() -> list[OrderListItem]:\n",[409,685,687,689,692],{"class":411,"line":686},11,[409,688,506],{"class":415},[409,690,691],{"class":415}," await",[409,693,694],{"class":419}," fetch_order_list()\n",[395,696,698],{"id":697},"_4-reuse-a-typeadapter-and-skip-re-validation","4. Reuse a TypeAdapter and skip re-validation",[400,700,702],{"className":402,"code":701,"language":404,"meta":405,"style":405},"from pydantic import TypeAdapter\n\n# Built once at module scope; reused for every serialization of this shape.\nORDERS = TypeAdapter(list[OrderListItem])\n\n\ndef dump_orders(items: list[OrderListItem]) -> bytes:\n    return ORDERS.dump_json(items)\n",[337,703,704,715,719,724,734,738,742,757],{"__ignoreMap":405},[409,705,706,708,710,712],{"class":411,"line":412},[409,707,582],{"class":415},[409,709,585],{"class":419},[409,711,416],{"class":415},[409,713,714],{"class":419}," TypeAdapter\n",[409,716,717],{"class":411,"line":423},[409,718,427],{"emptyLinePlaceholder":426},[409,720,721],{"class":411,"line":430},[409,722,723],{"class":529},"# Built once at module scope; reused for every serialization of this shape.\n",[409,725,726,729,731],{"class":411,"line":435},[409,727,728],{"class":448},"ORDERS",[409,730,452],{"class":415},[409,732,733],{"class":419}," TypeAdapter(list[OrderListItem])\n",[409,735,736],{"class":411,"line":467},[409,737,427],{"emptyLinePlaceholder":426},[409,739,740],{"class":411,"line":479},[409,741,427],{"emptyLinePlaceholder":426},[409,743,744,746,749,752,755],{"class":411,"line":497},[409,745,438],{"class":415},[409,747,748],{"class":441}," dump_orders",[409,750,751],{"class":419},"(items: list[OrderListItem]) -> ",[409,753,754],{"class":448},"bytes",[409,756,464],{"class":419},[409,758,759,761,764],{"class":411,"line":503},[409,760,506],{"class":415},[409,762,763],{"class":448}," ORDERS",[409,765,766],{"class":419},".dump_json(items)\n",[371,768,770],{"id":769},"edge-cases-and-gotchas","Edge Cases and Gotchas",[327,772,773,783,792],{},[330,774,775,778,779,782],{},[323,776,777],{},"Computed fields."," A ",[337,780,781],{},"computed_field"," runs on every serialization; cache its input if it is expensive.",[330,784,785,791],{},[323,786,787,790],{},[337,788,789],{},"by_alias"," everywhere."," Aliasing is cheap, but inconsistent alias conventions across nested models produce confusing output; standardize.",[330,793,794,797],{},[323,795,796],{},"Premature optimization."," Without profiling you may optimize a path that is not the bottleneck; measure first.",[371,799,801],{"id":800},"verification","Verification",[400,803,805],{"className":402,"code":804,"language":404,"meta":405,"style":405},"def test_serialization_within_budget(big_order):\n    # Guardrail on a representative payload; tune to your SLA.\n    assert profile_serialize(big_order, n=200) \u003C 5.0   # ms per call\n",[337,806,807,817,822],{"__ignoreMap":405},[409,808,809,811,814],{"class":411,"line":412},[409,810,438],{"class":415},[409,812,813],{"class":441}," test_serialization_within_budget",[409,815,816],{"class":419},"(big_order):\n",[409,818,819],{"class":411,"line":423},[409,820,821],{"class":529},"    # Guardrail on a representative payload; tune to your SLA.\n",[409,823,824,827,830,833,835,838,841,844,847],{"class":411,"line":430},[409,825,826],{"class":415},"    assert",[409,828,829],{"class":419}," profile_serialize(big_order, ",[409,831,832],{"class":662},"n",[409,834,473],{"class":415},[409,836,837],{"class":448},"200",[409,839,840],{"class":419},") ",[409,842,843],{"class":415},"\u003C",[409,845,846],{"class":448}," 5.0",[409,848,530],{"class":529},[371,850,852],{"id":851},"related-reading","Related Reading",[327,854,855,863],{},[330,856,857,860,861,357],{},[323,858,859],{},"Up to the topic:"," ",[362,862,365],{"href":364},[330,864,865,860,868,870,871,357],{},[323,866,867],{},"Related guides:",[362,869,49],{"href":369}," and ",[362,872,874],{"href":873},"\u002Fasync-background-tasks-observability\u002Fcaching-strategies\u002F","Caching Strategies",[876,877,878],"style",{},"html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}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);}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}",{"title":405,"searchDepth":423,"depth":423,"links":880},[881,882,883,889,890,891],{"id":373,"depth":423,"text":374},{"id":380,"depth":423,"text":381},{"id":392,"depth":423,"text":393,"children":884},[885,886,887,888],{"id":397,"depth":430,"text":398},{"id":533,"depth":430,"text":534},{"id":571,"depth":430,"text":572},{"id":697,"depth":430,"text":698},{"id":769,"depth":423,"text":770},{"id":800,"depth":423,"text":801},{"id":851,"depth":423,"text":852},"Speed up Pydantic v2 serialization in FastAPI: model_dump_json single-pass output, trimming fields, reusing TypeAdapter, avoiding re-validation, and profiling the real bottleneck.","md",{"slug":895,"type":896,"breadcrumb":897,"datePublished":907,"dateModified":908,"howto":909,"faq":927},"pydantic-model-serialization-performance","long_tail",[898,900,903,904],{"label":899,"path":518},"Home",{"label":901,"path":902},"Advanced Pydantic Validation & Serialization","\u002Fadvanced-pydantic-validation-serialization\u002F",{"label":365,"path":364},{"label":905,"path":906},"Pydantic Model Serialization Performance","\u002Fadvanced-pydantic-validation-serialization\u002Fperformance-optimization-for-models\u002Fpydantic-model-serialization-performance\u002F","2026-03-07","2026-06-18",{"name":910,"steps":911},"Improve Pydantic model serialization performance",[912,915,918,921,924],{"name":913,"text":914},"Profile a real payload","Measure serialization time on a representative response before changing anything.",{"name":916,"text":917},"Serialize in one pass","Use model_dump_json to emit JSON directly instead of dumping to a dict then encoding.",{"name":919,"text":920},"Trim the output","Return a response model with only the fields clients need.",{"name":922,"text":923},"Reuse TypeAdapter","Build a TypeAdapter once for non-model shapes and reuse it.",{"name":925,"text":926},"Avoid re-validation","Pass trusted models through without re-parsing, and use model_construct for known-good data.",[928,931,934],{"q":929,"a":930},"What is the fastest way to serialize a Pydantic model in FastAPI?","Emit JSON in a single pass with model_dump_json, which serializes on the Rust core without building an intermediate Python dict. Returning the smallest response model that satisfies the client further reduces work, because serialization cost scales with the number of fields and nodes visited.",{"q":932,"a":933},"Does returning the model directly from a route serialize efficiently?","FastAPI serializes the return value against the response_model. Returning a precise response model lets it emit exactly the needed fields efficiently. Returning a large ORM-backed or over-broad model forces it to serialize fields nobody needs, which is the most common avoidable cost on a hot endpoint.",{"q":935,"a":936},"How much does avoiding re-validation help serialization throughput?","Re-validation is separate from serialization, but on a hot path the two compound: re-parsing a trusted object runs every validator before you even serialize. Passing trusted models through and using model_construct for known-good data removes that duplicated validation, which often dominates the avoidable cost.",{"title":61,"description":892},"QjQZFYk6kuUYROE531t0i_KFZ2Xk2uxeVrGjyDu8oiQ",[940,940],null,1781809863444]