FastAPI: From Basics to Production · Deployment, Observability and Performance
Performance Tuning
Find and fix the real bottlenecks in FastAPI services.
Most FastAPI slowness comes from blocking calls in async code, N+1 queries, missing indexes, chatty external calls and large payloads. Profile (py-spy, pyinstrument, traces), then: use async drivers end to end, eager-load relationships, add indexes, cache hot reads in Redis, run independent I/O concurrently, paginate, compress responses (GZip), and consider faster JSON (ORJSONResponse) for very large payloads. Load test with Locust or k6 to verify.
from fastapi.middleware.gzip import GZipMiddleware
import asyncio
app.add_middleware(GZipMiddleware, minimum_size=1024)
sem = asyncio.Semaphore(20)
async def fetch_price(http, sku: str) -> int:
async with sem: # bounded concurrency
r = await http.get(f"https://pricing/skus/{sku}")
r.raise_for_status()
return r.json()["price_cents"]
async def prices(http, skus: list[str]) -> dict[str, int]:
results = await asyncio.gather(*(fetch_price(http, s) for s in skus))
return dict(zip(skus, results))
py-spy top --pid $(pgrep -f "uvicorn") # live CPU profile of a worker
Common pitfalls
- Optimizing JSON serialization while the database dominates latency.
- Unbounded concurrency overwhelming downstream services.
- Load testing with unrealistic data volumes.
Key points
- Profile first
- Async end to end; bounded concurrency
- Fix queries, cache hot reads, paginate
Further reading: FastAPI: Custom responses
Practice questions
Your async endpoint's latency spikes under load while CPU is low. What's a likely cause?
Answer
Blocking calls inside async code (sync DB driver, requests, file I/O) stalling the event loop, or connection pool exhaustion; check with profiling and pool metrics.
Why use a semaphore with asyncio.gather for many outbound calls?
Answer
To cap concurrency so you don't overwhelm the downstream service, exhaust connection pools or trigger rate limits.
Open in the app to mark lessons complete, take notes and track your progress.