FastAPI hits 50k requests per second on commodity hardware with the right setup. Most teams stop at 5k and conclude FastAPI is slow. The bottleneck is almost never FastAPI. Here is a tour of what we changed to get there.

Workers and processes

Default uvicorn with a single worker tops out around 5k RPS on synthetic load. Gunicorn with N uvicorn workers (N = CPU cores) gets us to 25k. Past that, the wins come from elsewhere.

Connection pooling

The single largest jump in our benchmarks: setting asyncpg pool sizes per worker to match the actual concurrent query count, not the defaults. We landed on min 5 / max 20 per worker, after measuring the actual saturation curve.

The bottleneck that surprised us

DNS. Every outbound HTTP call was resolving the hostname fresh. Caching the resolver doubled throughput on endpoints that hit downstream services.

What else mattered

Reproducing this yourself

Benchmark with realistic traffic, not "hello world." Use connection-reuse settings that match production. Run the load generator on a different machine than the server, on the same network. And measure latency percentiles, not just throughput.

Related reading