FastAPI performance optimization

Logo
Table of contents

FastAPI performance tuning

FastAPI is a great, high performance web framework but far from perfect. This document is intended to provide some tips and ideas to get the most out of it

Use these techniques to achieve 100-300% performance increase from your FastAPI application

All tested on the same sized Docker containers (2 CPU cores). The performance numbers below represent real CI-verified measurements.

Combined optimization impact

Each optimization below has a measurable, compounding effect. When applied together, the total improvement is multiplicative, not additive.

Sync endpoints

Optimization Impact Details
Gunicorn (1 worker) → FastAPI CLI (2 workers) +50-65% throughput Server runners
JSON → ORJSON response class +4-13% throughput JSON response classes
BaseHTTPMiddleware → Starlette ASGI +35-44% throughput (avoiding BaseHTTPMiddleware cost) Middleware
Best vs Worst combo +100% throughput Measured below

Async endpoints

Optimization Impact Details
Sync → Async endpoints +20-33% throughput Sync vs Async
Gunicorn (1 worker) → FastAPI CLI (2 workers) +50-65% throughput Server runners
JSON → ORJSON response class +4-13% throughput JSON response classes
BaseHTTPMiddleware → Starlette ASGI +35-44% throughput (avoiding BaseHTTPMiddleware cost) Middleware
Best vs Worst combo +297% throughput Measured below

Measured best vs worst configurations

CI run 30018301964 — all 4 jobs passed.

Using the big JSON response endpoint (1MB payload) across all tested combinations:

Configuration key: w{N} = N worker processes, t{N} = N threads per worker.

  • Gunicorn w1t0: Gunicorn with 1 worker process, 0 threads (single-process baseline)
  • FastAPI CLI w2: FastAPI CLI (fastapi run --workers 2) with 2 worker processes
  • ORJSON: ORJSONResponse (fast JSON serialization via orjson)
  • Starlette ASGI: Starlette native ASGI middleware (not BaseHTTPMiddleware)

Sync endpoint (/sync/big_json_response)

Configuration RPS Latency
Best: FastAPI CLI (2 workers) + async + ORJSON + Starlette ASGI 3405 29.4 ms
Worst: Gunicorn (1 worker, 0 threads) + sync + JSON + BaseHTTPMiddleware 1695 59.1 ms
Improvement +100.85% -29.7 ms

Async endpoint (/async/big_json_response)

Configuration RPS Latency
Best: FastAPI CLI (2 workers) + async + ORJSON + Starlette ASGI 3433 29.4 ms
Worst: Gunicorn (1 worker, 0 threads) + sync + JSON + BaseHTTPMiddleware 864 180.1 ms
Improvement +297% -150.7 ms

Small payload endpoints

Endpoint Best RPS Worst RPS Improvement
/sync/items/ 2081 974 +113.6%
/async/items/ 2656 867 +206.4%

The compounding effect

When you combine ALL optimizations:

Factor Worst config Best config
Server runner Gunicorn (1 worker, 0 threads) FastAPI CLI (2 workers)
Endpoint type Sync Async
Response class JSON ORJSON
Middleware BaseHTTPMiddleware Starlette ASGI (or none)
Nginx transport TCP port Unix socket
Combined RPS (big JSON) 864 3433
Combined improvement   ~4x throughput

The difference between a default FastAPI setup and a properly optimized one is 4x throughput on big JSON responses and 3x on small payloads. These are not theoretical numbers — they are measured in CI on identical Docker infrastructure (2 CPU cores per container).

All optimization topics

Fastapi Middleware performance tuning

Fastapi JSON response classes comparison

Gunicorn workers and threads

Nginx in front of FastAPI

Connection keepalive

Server Runners: Gunicorn vs Uvicorn vs FastAPI CLI

Sync / Async API Endpoints

Connection Pool Size of External Resources

Thread Pool Sizing (anyio tokens)

Per-Worker Connection Pool

Pool Sizing Calculator

Robustness & Reliability (Generic, not FastAPI-specific)

These patterns apply to any Python web application. They contribute to a robust and reliable application but are not FastAPI performance optimizations.

Retry Patterns and Circuit Breaker

Test environment

Stay tuned for new ideas:

FastAPI application profiling

Arbitrary place of code

Profiling middleware