[{"data":1,"prerenderedAt":1301},["ShallowReactive",2],{"page-\u002Fgetting-started-with-python-apis-for-builders\u002Fsetting-up-fastapi\u002F":3,"faq-schema-\u002Fgetting-started-with-python-apis-for-builders\u002Fsetting-up-fastapi\u002F":1280},{"id":4,"title":5,"body":6,"description":16,"extension":1274,"meta":1275,"navigation":142,"path":1276,"seo":1277,"stem":1278,"__hash__":1279},"content\u002Fgetting-started-with-python-apis-for-builders\u002Fsetting-up-fastapi\u002Findex.md","Setting Up FastAPI for Builders: A Step-by-Step Guide",{"type":7,"value":8,"toc":1266},"minimark",[9,13,17,23,39,44,47,56,61,72,77,469,473,476,497,502,735,739,746,753,758,988,992,995,1002,1007,1165,1169,1193,1197,1210,1224,1242,1248,1262],[10,11,5],"h1",{"id":12},"setting-up-fastapi-for-builders-a-step-by-step-guide",[14,15,16],"p",{},"FastAPI delivers production-ready performance with minimal boilerplate, making it the optimal framework for builders and side-hustlers prioritizing speed, scalability, and cloud cost control. This guide walks through environment initialization, type-safe routing, resilient error handling, and architecture tuning to keep compute spend low while maintaining high throughput.",[14,18,19],{},[20,21,22],"strong",{},"Key Advantages:",[24,25,26,30,33,36],"ul",{},[27,28,29],"li",{},"Async-first execution reduces server concurrency costs",[27,31,32],{},"Built-in OpenAPI documentation accelerates client integration",[27,34,35],{},"Strict Pydantic validation prevents downstream processing failures",[27,37,38],{},"Modular project structure supports iterative feature rollout",[40,41,43],"h2",{"id":42},"initialize-the-environment-project-structure","Initialize the Environment & Project Structure",[14,45,46],{},"Establish a lean, reproducible foundation for API development that scales without dependency bloat. Isolate your dependencies early to prevent package conflicts across projects, and enforce a modular directory layout that separates routing, data models, configuration, and utility logic.",[14,48,49,50,55],{},"When scaffolding your first service, remember that foundational API architecture dictates long-term maintainability and deployment velocity. For a comprehensive overview of the development lifecycle, consult ",[51,52,54],"a",{"href":53},"\u002Fgetting-started-with-python-apis-for-builders\u002F","Getting Started with Python APIs for Builders",".",[14,57,58],{},[20,59,60],{},"Recommended Directory Layout:",[62,63,68],"pre",{"className":64,"code":66,"language":67},[65],"language-text","my_api\u002F\n├── app\u002F\n│ ├── __init__.py\n│ ├── main.py\n│ ├── config.py\n│ ├── routers\u002F\n│ ├── models\u002F\n│ └── utils\u002F\n├── .env\n├── requirements.txt\n└── Dockerfile\n","text",[69,70,66],"code",{"__ignoreMap":71},"",[14,73,74],{},[20,75,76],{},"Core Setup & Async Route Declaration:",[62,78,82],{"className":79,"code":80,"language":81,"meta":71,"style":71},"language-python shiki shiki-themes github-light github-dark","import os\nfrom fastapi import FastAPI, HTTPException\nfrom pydantic import BaseModel, Field\nfrom typing import Optional\n\n# Load environment variables securely\nDATABASE_URL = os.getenv(\"DATABASE_URL\", \"sqlite:\u002F\u002F\u002F.\u002Fapp.db\")\nAPI_TIMEOUT = int(os.getenv(\"API_TIMEOUT\", \"10\"))\n\napp = FastAPI(title=\"Builder API\", version=\"1.0.0\")\n\nclass ItemCreate(BaseModel):\n name: str = Field(..., min_length=2, max_length=50)\n price: float = Field(..., gt=0)\n category: Optional[str] = None\n\n@app.post(\"\u002Fitems\u002F\", status_code=201)\nasync def create_item(item: ItemCreate):\n \"\"\"\n Async route with automatic payload validation.\n Rejects malformed requests before consuming compute resources.\n \"\"\"\n # Simulate async DB or external call with timeout awareness\n return {\"message\": f\"Created {item.name}\", \"cost\": item.price, \"timeout_budget\": API_TIMEOUT}\n","python",[69,83,84,97,111,124,137,144,151,177,202,207,240,245,264,303,330,346,351,374,389,395,401,407,412,418],{"__ignoreMap":71},[85,86,89,93],"span",{"class":87,"line":88},"line",1,[85,90,92],{"class":91},"szBVR","import",[85,94,96],{"class":95},"sVt8B"," os\n",[85,98,100,103,106,108],{"class":87,"line":99},2,[85,101,102],{"class":91},"from",[85,104,105],{"class":95}," fastapi ",[85,107,92],{"class":91},[85,109,110],{"class":95}," FastAPI, HTTPException\n",[85,112,114,116,119,121],{"class":87,"line":113},3,[85,115,102],{"class":91},[85,117,118],{"class":95}," pydantic ",[85,120,92],{"class":91},[85,122,123],{"class":95}," BaseModel, Field\n",[85,125,127,129,132,134],{"class":87,"line":126},4,[85,128,102],{"class":91},[85,130,131],{"class":95}," typing ",[85,133,92],{"class":91},[85,135,136],{"class":95}," Optional\n",[85,138,140],{"class":87,"line":139},5,[85,141,143],{"emptyLinePlaceholder":142},true,"\n",[85,145,147],{"class":87,"line":146},6,[85,148,150],{"class":149},"sJ8bj","# Load environment variables securely\n",[85,152,154,158,161,164,168,171,174],{"class":87,"line":153},7,[85,155,157],{"class":156},"sj4cs","DATABASE_URL",[85,159,160],{"class":91}," =",[85,162,163],{"class":95}," os.getenv(",[85,165,167],{"class":166},"sZZnC","\"DATABASE_URL\"",[85,169,170],{"class":95},", ",[85,172,173],{"class":166},"\"sqlite:\u002F\u002F\u002F.\u002Fapp.db\"",[85,175,176],{"class":95},")\n",[85,178,180,183,185,188,191,194,196,199],{"class":87,"line":179},8,[85,181,182],{"class":156},"API_TIMEOUT",[85,184,160],{"class":91},[85,186,187],{"class":156}," int",[85,189,190],{"class":95},"(os.getenv(",[85,192,193],{"class":166},"\"API_TIMEOUT\"",[85,195,170],{"class":95},[85,197,198],{"class":166},"\"10\"",[85,200,201],{"class":95},"))\n",[85,203,205],{"class":87,"line":204},9,[85,206,143],{"emptyLinePlaceholder":142},[85,208,210,213,216,219,223,225,228,230,233,235,238],{"class":87,"line":209},10,[85,211,212],{"class":95},"app ",[85,214,215],{"class":91},"=",[85,217,218],{"class":95}," FastAPI(",[85,220,222],{"class":221},"s4XuR","title",[85,224,215],{"class":91},[85,226,227],{"class":166},"\"Builder API\"",[85,229,170],{"class":95},[85,231,232],{"class":221},"version",[85,234,215],{"class":91},[85,236,237],{"class":166},"\"1.0.0\"",[85,239,176],{"class":95},[85,241,243],{"class":87,"line":242},11,[85,244,143],{"emptyLinePlaceholder":142},[85,246,248,251,255,258,261],{"class":87,"line":247},12,[85,249,250],{"class":91},"class",[85,252,254],{"class":253},"sScJk"," ItemCreate",[85,256,257],{"class":95},"(",[85,259,260],{"class":253},"BaseModel",[85,262,263],{"class":95},"):\n",[85,265,267,270,273,275,278,281,283,286,288,291,293,296,298,301],{"class":87,"line":266},13,[85,268,269],{"class":95}," name: ",[85,271,272],{"class":156},"str",[85,274,160],{"class":91},[85,276,277],{"class":95}," Field(",[85,279,280],{"class":156},"...",[85,282,170],{"class":95},[85,284,285],{"class":221},"min_length",[85,287,215],{"class":91},[85,289,290],{"class":156},"2",[85,292,170],{"class":95},[85,294,295],{"class":221},"max_length",[85,297,215],{"class":91},[85,299,300],{"class":156},"50",[85,302,176],{"class":95},[85,304,306,309,312,314,316,318,320,323,325,328],{"class":87,"line":305},14,[85,307,308],{"class":95}," price: ",[85,310,311],{"class":156},"float",[85,313,160],{"class":91},[85,315,277],{"class":95},[85,317,280],{"class":156},[85,319,170],{"class":95},[85,321,322],{"class":221},"gt",[85,324,215],{"class":91},[85,326,327],{"class":156},"0",[85,329,176],{"class":95},[85,331,333,336,338,341,343],{"class":87,"line":332},15,[85,334,335],{"class":95}," category: Optional[",[85,337,272],{"class":156},[85,339,340],{"class":95},"] ",[85,342,215],{"class":91},[85,344,345],{"class":156}," None\n",[85,347,349],{"class":87,"line":348},16,[85,350,143],{"emptyLinePlaceholder":142},[85,352,354,357,359,362,364,367,369,372],{"class":87,"line":353},17,[85,355,356],{"class":253},"@app.post",[85,358,257],{"class":95},[85,360,361],{"class":166},"\"\u002Fitems\u002F\"",[85,363,170],{"class":95},[85,365,366],{"class":221},"status_code",[85,368,215],{"class":91},[85,370,371],{"class":156},"201",[85,373,176],{"class":95},[85,375,377,380,383,386],{"class":87,"line":376},18,[85,378,379],{"class":91},"async",[85,381,382],{"class":91}," def",[85,384,385],{"class":253}," create_item",[85,387,388],{"class":95},"(item: ItemCreate):\n",[85,390,392],{"class":87,"line":391},19,[85,393,394],{"class":166}," \"\"\"\n",[85,396,398],{"class":87,"line":397},20,[85,399,400],{"class":166}," Async route with automatic payload validation.\n",[85,402,404],{"class":87,"line":403},21,[85,405,406],{"class":166}," Rejects malformed requests before consuming compute resources.\n",[85,408,410],{"class":87,"line":409},22,[85,411,394],{"class":166},[85,413,415],{"class":87,"line":414},23,[85,416,417],{"class":149}," # Simulate async DB or external call with timeout awareness\n",[85,419,421,424,427,430,433,436,439,442,445,448,451,453,456,459,462,464,466],{"class":87,"line":420},24,[85,422,423],{"class":91}," return",[85,425,426],{"class":95}," {",[85,428,429],{"class":166},"\"message\"",[85,431,432],{"class":95},": ",[85,434,435],{"class":91},"f",[85,437,438],{"class":166},"\"Created ",[85,440,441],{"class":156},"{",[85,443,444],{"class":95},"item.name",[85,446,447],{"class":156},"}",[85,449,450],{"class":166},"\"",[85,452,170],{"class":95},[85,454,455],{"class":166},"\"cost\"",[85,457,458],{"class":95},": item.price, ",[85,460,461],{"class":166},"\"timeout_budget\"",[85,463,432],{"class":95},[85,465,182],{"class":156},[85,467,468],{"class":95},"}\n",[40,470,472],{"id":471},"define-endpoints-validate-payloads","Define Endpoints & Validate Payloads",[14,474,475],{},"Build type-safe routes that reject malformed requests before consuming compute resources. FastAPI leverages Pydantic models for strict schema enforcement, automatically parsing JSON bodies, path parameters, and query strings while applying type coercion.",[14,477,478,479,170,482,170,485,170,488,491,492,496],{},"Structure your endpoints to align with standard HTTP methods (",[69,480,481],{},"GET",[69,483,484],{},"POST",[69,486,487],{},"PUT",[69,489,490],{},"DELETE","). This ensures predictable client behavior and simplifies caching strategies. When deciding between resource-oriented routing and query-driven architectures, review ",[51,493,495],{"href":494},"\u002Fgetting-started-with-python-apis-for-builders\u002Funderstanding-rest-vs-graphql\u002F","Understanding REST vs GraphQL"," to align your design with your data access patterns and team velocity.",[14,498,499],{},[20,500,501],{},"Validation & Parameter Handling:",[62,503,505],{"className":79,"code":504,"language":81,"meta":71,"style":71},"from fastapi import Query, Path\n\n@app.get(\"\u002Fitems\u002F{item_id}\")\nasync def get_item(\n item_id: int = Path(..., gt=0, description=\"Unique item identifier\"),\n include_metadata: bool = Query(False, description=\"Toggle verbose response\")\n):\n # FastAPI automatically validates types and ranges\n if item_id == 999:\n raise HTTPException(status_code=404, detail=\"Item not found\")\n \n return {\n \"id\": item_id,\n \"name\": \"Sample Item\",\n \"metadata\": {\"cached\": True} if include_metadata else None\n }\n",[69,506,507,518,522,539,551,587,614,618,623,640,667,672,679,687,700,730],{"__ignoreMap":71},[85,508,509,511,513,515],{"class":87,"line":88},[85,510,102],{"class":91},[85,512,105],{"class":95},[85,514,92],{"class":91},[85,516,517],{"class":95}," Query, Path\n",[85,519,520],{"class":87,"line":99},[85,521,143],{"emptyLinePlaceholder":142},[85,523,524,527,529,532,535,537],{"class":87,"line":113},[85,525,526],{"class":253},"@app.get",[85,528,257],{"class":95},[85,530,531],{"class":166},"\"\u002Fitems\u002F",[85,533,534],{"class":156},"{item_id}",[85,536,450],{"class":166},[85,538,176],{"class":95},[85,540,541,543,545,548],{"class":87,"line":126},[85,542,379],{"class":91},[85,544,382],{"class":91},[85,546,547],{"class":253}," get_item",[85,549,550],{"class":95},"(\n",[85,552,553,556,559,561,564,566,568,570,572,574,576,579,581,584],{"class":87,"line":139},[85,554,555],{"class":95}," item_id: ",[85,557,558],{"class":156},"int",[85,560,160],{"class":91},[85,562,563],{"class":95}," Path(",[85,565,280],{"class":156},[85,567,170],{"class":95},[85,569,322],{"class":221},[85,571,215],{"class":91},[85,573,327],{"class":156},[85,575,170],{"class":95},[85,577,578],{"class":221},"description",[85,580,215],{"class":91},[85,582,583],{"class":166},"\"Unique item identifier\"",[85,585,586],{"class":95},"),\n",[85,588,589,592,595,597,600,603,605,607,609,612],{"class":87,"line":146},[85,590,591],{"class":95}," include_metadata: ",[85,593,594],{"class":156},"bool",[85,596,160],{"class":91},[85,598,599],{"class":95}," Query(",[85,601,602],{"class":156},"False",[85,604,170],{"class":95},[85,606,578],{"class":221},[85,608,215],{"class":91},[85,610,611],{"class":166},"\"Toggle verbose response\"",[85,613,176],{"class":95},[85,615,616],{"class":87,"line":153},[85,617,263],{"class":95},[85,619,620],{"class":87,"line":179},[85,621,622],{"class":149}," # FastAPI automatically validates types and ranges\n",[85,624,625,628,631,634,637],{"class":87,"line":204},[85,626,627],{"class":91}," if",[85,629,630],{"class":95}," item_id ",[85,632,633],{"class":91},"==",[85,635,636],{"class":156}," 999",[85,638,639],{"class":95},":\n",[85,641,642,645,648,650,652,655,657,660,662,665],{"class":87,"line":209},[85,643,644],{"class":91}," raise",[85,646,647],{"class":95}," HTTPException(",[85,649,366],{"class":221},[85,651,215],{"class":91},[85,653,654],{"class":156},"404",[85,656,170],{"class":95},[85,658,659],{"class":221},"detail",[85,661,215],{"class":91},[85,663,664],{"class":166},"\"Item not found\"",[85,666,176],{"class":95},[85,668,669],{"class":87,"line":242},[85,670,671],{"class":95}," \n",[85,673,674,676],{"class":87,"line":247},[85,675,423],{"class":91},[85,677,678],{"class":95}," {\n",[85,680,681,684],{"class":87,"line":266},[85,682,683],{"class":166}," \"id\"",[85,685,686],{"class":95},": item_id,\n",[85,688,689,692,694,697],{"class":87,"line":305},[85,690,691],{"class":166}," \"name\"",[85,693,432],{"class":95},[85,695,696],{"class":166},"\"Sample Item\"",[85,698,699],{"class":95},",\n",[85,701,702,705,708,711,713,716,719,722,725,728],{"class":87,"line":332},[85,703,704],{"class":166}," \"metadata\"",[85,706,707],{"class":95},": {",[85,709,710],{"class":166},"\"cached\"",[85,712,432],{"class":95},[85,714,715],{"class":156},"True",[85,717,718],{"class":95},"} ",[85,720,721],{"class":91},"if",[85,723,724],{"class":95}," include_metadata ",[85,726,727],{"class":91},"else",[85,729,345],{"class":156},[85,731,732],{"class":87,"line":348},[85,733,734],{"class":95}," }\n",[40,736,738],{"id":737},"implement-production-grade-error-handling","Implement Production-Grade Error Handling",[14,740,741,742,745],{},"Prevent silent failures, standardize client feedback, and gracefully manage external service dependencies. Always raise ",[69,743,744],{},"HTTPException"," with structured JSON payloads and appropriate status codes for expected failures. Register global exception handlers via middleware to catch unhandled errors and log them safely.",[14,747,748,749,55],{},"When integrating third-party services, implement exponential backoff and retry logic to absorb transient network failures. For detailed patterns on outbound call resilience and timeout configuration, see ",[51,750,752],{"href":751},"\u002Fgetting-started-with-python-apis-for-builders\u002Fmaking-http-requests-with-requests-library\u002F","Making HTTP Requests with Requests Library",[14,754,755],{},[20,756,757],{},"Global Exception Handler & Structured Fallbacks:",[62,759,761],{"className":79,"code":760,"language":81,"meta":71,"style":71},"from fastapi import Request\nfrom fastapi.responses import JSONResponse\nimport logging\n\nlogger = logging.getLogger(\"uvicorn.error\")\n\n@app.exception_handler(HTTPException)\nasync def http_exception_handler(request: Request, exc: HTTPException):\n return JSONResponse(\n status_code=exc.status_code,\n content={\"error\": exc.detail, \"path\": request.url.path}\n )\n\n@app.exception_handler(Exception)\nasync def global_exception_handler(request: Request, exc: Exception):\n logger.error(f\"Unhandled error on {request.url.path}: {exc}\")\n return JSONResponse(\n status_code=500,\n content={\"error\": \"Internal Server Error\", \"detail\": \"A transient failure occurred.\"}\n )\n",[69,762,763,774,786,793,797,812,816,824,836,843,853,874,879,883,894,910,940,946,957,984],{"__ignoreMap":71},[85,764,765,767,769,771],{"class":87,"line":88},[85,766,102],{"class":91},[85,768,105],{"class":95},[85,770,92],{"class":91},[85,772,773],{"class":95}," Request\n",[85,775,776,778,781,783],{"class":87,"line":99},[85,777,102],{"class":91},[85,779,780],{"class":95}," fastapi.responses ",[85,782,92],{"class":91},[85,784,785],{"class":95}," JSONResponse\n",[85,787,788,790],{"class":87,"line":113},[85,789,92],{"class":91},[85,791,792],{"class":95}," logging\n",[85,794,795],{"class":87,"line":126},[85,796,143],{"emptyLinePlaceholder":142},[85,798,799,802,804,807,810],{"class":87,"line":139},[85,800,801],{"class":95},"logger ",[85,803,215],{"class":91},[85,805,806],{"class":95}," logging.getLogger(",[85,808,809],{"class":166},"\"uvicorn.error\"",[85,811,176],{"class":95},[85,813,814],{"class":87,"line":146},[85,815,143],{"emptyLinePlaceholder":142},[85,817,818,821],{"class":87,"line":153},[85,819,820],{"class":253},"@app.exception_handler",[85,822,823],{"class":95},"(HTTPException)\n",[85,825,826,828,830,833],{"class":87,"line":179},[85,827,379],{"class":91},[85,829,382],{"class":91},[85,831,832],{"class":253}," http_exception_handler",[85,834,835],{"class":95},"(request: Request, exc: HTTPException):\n",[85,837,838,840],{"class":87,"line":204},[85,839,423],{"class":91},[85,841,842],{"class":95}," JSONResponse(\n",[85,844,845,848,850],{"class":87,"line":209},[85,846,847],{"class":221}," status_code",[85,849,215],{"class":91},[85,851,852],{"class":95},"exc.status_code,\n",[85,854,855,858,860,862,865,868,871],{"class":87,"line":242},[85,856,857],{"class":221}," content",[85,859,215],{"class":91},[85,861,441],{"class":95},[85,863,864],{"class":166},"\"error\"",[85,866,867],{"class":95},": exc.detail, ",[85,869,870],{"class":166},"\"path\"",[85,872,873],{"class":95},": request.url.path}\n",[85,875,876],{"class":87,"line":247},[85,877,878],{"class":95}," )\n",[85,880,881],{"class":87,"line":266},[85,882,143],{"emptyLinePlaceholder":142},[85,884,885,887,889,892],{"class":87,"line":305},[85,886,820],{"class":253},[85,888,257],{"class":95},[85,890,891],{"class":156},"Exception",[85,893,176],{"class":95},[85,895,896,898,900,903,906,908],{"class":87,"line":332},[85,897,379],{"class":91},[85,899,382],{"class":91},[85,901,902],{"class":253}," global_exception_handler",[85,904,905],{"class":95},"(request: Request, exc: ",[85,907,891],{"class":156},[85,909,263],{"class":95},[85,911,912,915,917,920,922,925,927,929,931,934,936,938],{"class":87,"line":348},[85,913,914],{"class":95}," logger.error(",[85,916,435],{"class":91},[85,918,919],{"class":166},"\"Unhandled error on ",[85,921,441],{"class":156},[85,923,924],{"class":95},"request.url.path",[85,926,447],{"class":156},[85,928,432],{"class":166},[85,930,441],{"class":156},[85,932,933],{"class":95},"exc",[85,935,447],{"class":156},[85,937,450],{"class":166},[85,939,176],{"class":95},[85,941,942,944],{"class":87,"line":353},[85,943,423],{"class":91},[85,945,842],{"class":95},[85,947,948,950,952,955],{"class":87,"line":376},[85,949,847],{"class":221},[85,951,215],{"class":91},[85,953,954],{"class":156},"500",[85,956,699],{"class":95},[85,958,959,961,963,965,967,969,972,974,977,979,982],{"class":87,"line":391},[85,960,857],{"class":221},[85,962,215],{"class":91},[85,964,441],{"class":95},[85,966,864],{"class":166},[85,968,432],{"class":95},[85,970,971],{"class":166},"\"Internal Server Error\"",[85,973,170],{"class":95},[85,975,976],{"class":166},"\"detail\"",[85,978,432],{"class":95},[85,980,981],{"class":166},"\"A transient failure occurred.\"",[85,983,468],{"class":95},[85,985,986],{"class":87,"line":397},[85,987,878],{"class":95},[40,989,991],{"id":990},"optimize-for-cost-aware-architecture","Optimize for Cost-Aware Architecture",[14,993,994],{},"Configure the runtime to minimize cloud compute spend while maintaining predictable latency under load. Async execution allows a single worker to handle thousands of concurrent I\u002FO-bound requests, drastically reducing the need for horizontal scaling.",[14,996,997,998,55],{},"Tune Uvicorn worker counts to match available vCPUs, avoiding memory thrashing. Implement connection pooling for database and external service clients, and enable gzip\u002Fbrotli response compression to reduce bandwidth costs. When evaluating framework overhead, async capabilities, and scaling economics, compare your deployment options in ",[51,999,1001],{"href":1000},"\u002Fgetting-started-with-python-apis-for-builders\u002Fsetting-up-fastapi\u002Ffastapi-vs-flask-for-api-development\u002F","FastAPI vs Flask for API development",[14,1003,1004],{},[20,1005,1006],{},"Production Server Configuration:",[62,1008,1010],{"className":79,"code":1009,"language":81,"meta":71,"style":71},"import uvicorn\nimport os\n\nif __name__ == \"__main__\":\n # Match workers to vCPU count (2-4 for most low-cost VPS instances)\n WORKER_COUNT = int(os.getenv(\"WORKER_COUNT\", \"2\"))\n \n uvicorn.run(\n \"app.main:app\",\n host=\"0.0.0.0\",\n port=8000,\n workers=WORKER_COUNT,\n log_level=\"warning\",\n loop=\"uvloop\", # Drop-in replacement for asyncio, ~3x faster\n access_log=False # Disable to reduce I\u002FO overhead in production\n )\n",[69,1011,1012,1019,1025,1029,1044,1049,1070,1074,1079,1086,1098,1110,1122,1134,1149,1161],{"__ignoreMap":71},[85,1013,1014,1016],{"class":87,"line":88},[85,1015,92],{"class":91},[85,1017,1018],{"class":95}," uvicorn\n",[85,1020,1021,1023],{"class":87,"line":99},[85,1022,92],{"class":91},[85,1024,96],{"class":95},[85,1026,1027],{"class":87,"line":113},[85,1028,143],{"emptyLinePlaceholder":142},[85,1030,1031,1033,1036,1039,1042],{"class":87,"line":126},[85,1032,721],{"class":91},[85,1034,1035],{"class":156}," __name__",[85,1037,1038],{"class":91}," ==",[85,1040,1041],{"class":166}," \"__main__\"",[85,1043,639],{"class":95},[85,1045,1046],{"class":87,"line":139},[85,1047,1048],{"class":149}," # Match workers to vCPU count (2-4 for most low-cost VPS instances)\n",[85,1050,1051,1054,1056,1058,1060,1063,1065,1068],{"class":87,"line":146},[85,1052,1053],{"class":156}," WORKER_COUNT",[85,1055,160],{"class":91},[85,1057,187],{"class":156},[85,1059,190],{"class":95},[85,1061,1062],{"class":166},"\"WORKER_COUNT\"",[85,1064,170],{"class":95},[85,1066,1067],{"class":166},"\"2\"",[85,1069,201],{"class":95},[85,1071,1072],{"class":87,"line":153},[85,1073,671],{"class":95},[85,1075,1076],{"class":87,"line":179},[85,1077,1078],{"class":95}," uvicorn.run(\n",[85,1080,1081,1084],{"class":87,"line":204},[85,1082,1083],{"class":166}," \"app.main:app\"",[85,1085,699],{"class":95},[85,1087,1088,1091,1093,1096],{"class":87,"line":209},[85,1089,1090],{"class":221}," host",[85,1092,215],{"class":91},[85,1094,1095],{"class":166},"\"0.0.0.0\"",[85,1097,699],{"class":95},[85,1099,1100,1103,1105,1108],{"class":87,"line":242},[85,1101,1102],{"class":221}," port",[85,1104,215],{"class":91},[85,1106,1107],{"class":156},"8000",[85,1109,699],{"class":95},[85,1111,1112,1115,1117,1120],{"class":87,"line":247},[85,1113,1114],{"class":221}," workers",[85,1116,215],{"class":91},[85,1118,1119],{"class":156},"WORKER_COUNT",[85,1121,699],{"class":95},[85,1123,1124,1127,1129,1132],{"class":87,"line":266},[85,1125,1126],{"class":221}," log_level",[85,1128,215],{"class":91},[85,1130,1131],{"class":166},"\"warning\"",[85,1133,699],{"class":95},[85,1135,1136,1139,1141,1144,1146],{"class":87,"line":305},[85,1137,1138],{"class":221}," loop",[85,1140,215],{"class":91},[85,1142,1143],{"class":166},"\"uvloop\"",[85,1145,170],{"class":95},[85,1147,1148],{"class":149},"# Drop-in replacement for asyncio, ~3x faster\n",[85,1150,1151,1154,1156,1158],{"class":87,"line":332},[85,1152,1153],{"class":221}," access_log",[85,1155,215],{"class":91},[85,1157,602],{"class":156},[85,1159,1160],{"class":149}," # Disable to reduce I\u002FO overhead in production\n",[85,1162,1163],{"class":87,"line":348},[85,1164,878],{"class":95},[40,1166,1168],{"id":1167},"common-mistakes","Common Mistakes",[24,1170,1171,1181,1184,1187,1190],{},[27,1172,1173,1174,170,1177,1180],{},"Using synchronous blocking libraries (e.g., ",[69,1175,1176],{},"requests",[69,1178,1179],{},"time.sleep",") inside async routes, causing thread starvation and degraded throughput",[27,1182,1183],{},"Skipping Pydantic validation and trusting raw request bodies, leading to downstream crashes and unpredictable state",[27,1185,1186],{},"Hardcoding API keys and secrets instead of injecting them via environment variables or secret managers",[27,1188,1189],{},"Over-provisioning Uvicorn workers beyond available CPU cores, causing memory thrashing and higher cloud bills",[27,1191,1192],{},"Neglecting to implement global exception handlers, exposing raw stack traces and internal architecture in production responses",[40,1194,1196],{"id":1195},"faq","FAQ",[14,1198,1199,1202,1203,1205,1206,1209],{},[20,1200,1201],{},"How many Uvicorn workers should I run to balance cost and performance?","\nStart with ",[69,1204,290],{}," to ",[69,1207,1208],{},"4"," workers, matching your instance's vCPU count. FastAPI's async nature handles high concurrency per worker, so adding more workers rarely improves I\u002FO-bound throughput and only increases memory overhead.",[14,1211,1212,1215,1216,1219,1220,1223],{},[20,1213,1214],{},"Does FastAPI automatically handle JSON serialization for Pydantic models?","\nYes. Return Pydantic models or dictionaries directly from your route functions. FastAPI uses ",[69,1217,1218],{},"orjson"," or standard ",[69,1221,1222],{},"json"," under the hood to serialize responses, including automatic datetime and UUID formatting.",[14,1225,1226,1229,1230,1233,1234,1237,1238,1241],{},[20,1227,1228],{},"What is the best way to implement retry logic for flaky external APIs?","\nUse ",[69,1231,1232],{},"tenacity"," or ",[69,1235,1236],{},"httpx"," with built-in retry decorators. Configure exponential backoff with jitter, set strict timeouts, and limit retry attempts to ",[69,1239,1240],{},"3"," to prevent cascading latency spikes.",[14,1243,1244,1247],{},[20,1245,1246],{},"Can I run FastAPI on a low-cost VPS without performance degradation?","\nAbsolutely. Async-first execution, connection pooling, and response compression allow a $5–$10 VPS to handle thousands of concurrent requests efficiently. Avoid synchronous database drivers and heavy ORM overhead.",[14,1249,1250,1253,1254,1257,1258,1261],{},[20,1251,1252],{},"How do I enable OpenAPI documentation for client testing during development?","\nFastAPI auto-generates interactive docs at ",[69,1255,1256],{},"\u002Fdocs"," (Swagger UI) and ",[69,1259,1260],{},"\u002Fredoc",". No additional configuration is required. In production, disable or password-protect these endpoints to prevent information disclosure.",[1263,1264,1265],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":71,"searchDepth":99,"depth":99,"links":1267},[1268,1269,1270,1271,1272,1273],{"id":42,"depth":99,"text":43},{"id":471,"depth":99,"text":472},{"id":737,"depth":99,"text":738},{"id":990,"depth":99,"text":991},{"id":1167,"depth":99,"text":1168},{"id":1195,"depth":99,"text":1196},"md",{},"\u002Fgetting-started-with-python-apis-for-builders\u002Fsetting-up-fastapi",{"title":5,"description":16},"getting-started-with-python-apis-for-builders\u002Fsetting-up-fastapi\u002Findex","p4WySPFXm267PPQDsKpR-mo_8gSsdpmWRXQry0jwujY",{"@context":1281,"@type":1282,"mainEntity":1283},"https:\u002F\u002Fschema.org","FAQPage",[1284,1289,1292,1295,1298],{"@type":1285,"name":1201,"acceptedAnswer":1286},"Question",{"@type":1287,"text":1288},"Answer","Start with 2 to 4 workers, matching your instance's vCPU count. FastAPI's async nature handles high concurrency per worker, so adding more workers rarely improves I\u002FO-bound throughput and only increases memory overhead.",{"@type":1285,"name":1214,"acceptedAnswer":1290},{"@type":1287,"text":1291},"Yes. Return Pydantic models or dictionaries directly from your route functions. FastAPI uses orjson or standard json under the hood to serialize responses, including automatic datetime and UUID formatting.",{"@type":1285,"name":1228,"acceptedAnswer":1293},{"@type":1287,"text":1294},"Use tenacity or httpx with built-in retry decorators. Configure exponential backoff with jitter, set strict timeouts, and limit retry attempts to 3 to prevent cascading latency spikes.",{"@type":1285,"name":1246,"acceptedAnswer":1296},{"@type":1287,"text":1297},"Absolutely. Async-first execution, connection pooling, and response compression allow a $5–$10 VPS to handle thousands of concurrent requests efficiently. Avoid synchronous database drivers and heavy ORM overhead.",{"@type":1285,"name":1252,"acceptedAnswer":1299},{"@type":1287,"text":1300},"FastAPI auto-generates interactive docs at \u002Fdocs (Swagger UI) and \u002Fredoc. No additional configuration is required. In production, disable or password-protect these endpoints to prevent information disclosure.",1778017885593]