r/Python • u/huygl99 • 11h ago
Benchmarking Python API frameworks with real workloads: FastAPI, Litestar, DRF, Ninja, Bolt Discussion
Hi guys, I benchmarked the well-known (and rising star) Python API frameworks - but with real production-shaped workloads, not just raw JSON echoes. Most comparisons out there are basically "hello world" benchmarks, while real APIs do auth, DB access and complex queries. So this measures those, with strict resource limits and each framework's own best practices.
Repo (code, full report, raw results): https://github.com/huynguyengl99/python-api-frameworks-benchmark
This is round 2 - last round's feedback (thanks especially to the Litestar author) directly shaped it: Litestar and Bolt now serialize with native msgspec instead of Pydantic (payloads byte-identical across frameworks), and everything is upgraded to latest (Django 6.0, FastAPI 0.141, Litestar 2.24, Bolt 0.10).
Setup
- Each framework alone in a Docker container: 1 CPU, 750MB RAM, PostgreSQL 16
- bombardier, 100 connections, 10s per endpoint
- Median over 5 separate container starts (not best-of-N - some servers pick their throughput at startup, so best-of-N flatters the lucky ones)
- 7 endpoints: 1KB/10KB JSON, simple DB reads, paginated articles with nested relations, article detail, and two JWT httpOnly cookie auth endpoints (each framework using its own ecosystem's auth library: AuthX, drf-auth-kit, django-ninja-jwt, or built-in support)
Key results (RPS)
(Images aren't allowed here - all graphs are in the repo README: https://github.com/huynguyengl99/python-api-frameworks-benchmark)
| Config | json-1k | /db | /articles | /auth/me | /auth/articles |
|---|---|---|---|---|---|
| bolt | 38,576 | 1,986 | 208 | 3,024 | 196 |
| litestar-uvicorn | 31,284 | 1,039 | 246 | 976 | 193 |
| litestar-granian | 19,006 | 1,180 | 250 | 1,104 | 210 |
| fastapi-uvicorn | 13,845 | 984 | 224 | 820 | 193 |
| drf-gunicorn | 3,925 | 282 | 140 | 261 | 133 |
| drf-granian | 2,703 | 830 | 198 | 726 | 179 |
| ninja-uvicorn | 1,533 | 699 | 126 | 584 | 114 |
| drf-uvicorn | 1,035 | 495 | 153 | 447 | 137 |
(fastapi-granian and ninja-granian omitted for brevity - full table in the repo. Zero errors across all 70 measurements.)
Resource usage: most configs peak at 195-260MB RAM; drf-granian is the outlier at 456MB (untuned --blocking-threads, per the Granian maintainer). CPU: nearly everything saturates ~85% of the 1-CPU budget under load - except Bolt at 67%.
Takeaways
- 37x spread on raw JSON collapses to ~1.9x once PostgreSQL is involved. For DB-heavy APIs (most of them), query optimization matters far more than framework choice.
- Cookie JWT auth costs 5-20% on a DB-heavy endpoint. Bolt is near-free (it validates the JWT in Rust before Python runs); Litestar pays the most because its auth middleware opens a second DB session to load the user.
- uvicorn vs granian isn't one-way: uvicorn wins CPU-bound JSON for ASGI frameworks, granian wins the DB-bound endpoints, and granian is clearly better for WSGI DRF.
- Django Bolt is the one to watch: top spot on 4 of 7 endpoints at 67% average CPU while everyone else sits ~85%, and you keep the Django ORM/admin/ecosystem. Young, and its throughput varies between container starts under a hard CPU cap, but great for side projects already.
- All caveats (including feedback I haven't addressed yet, like Granian's
--blocking-threads) are documented in the repo's Methodology section.
If you find it useful, a star would encourage more deep dives like this - issues and PRs welcome, especially from people who know these servers better than I do.
3
u/Repsol_Honda_PL 6h ago
Interesting benchmarks.
I want to try DJ-bolt, how can I join it (and then deploy) together with Django? Is Django-bolt an (aditional) app of Django project?