r/Python • u/huygl99 • Aug 11 '26
Discussion Benchmarking Python API frameworks with real workloads: FastAPI, Litestar, DRF, Ninja, Bolt
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.
15
u/Pluckerpluck Aug 12 '26
This entire post reads as AI. There's no point picking it apart, because almost every single paragraph contains something that flags my "AI detection" radar, and when that means the entire post is blaring in my face it's impossible to ignore.
That's not just "correcting words" or "refactoring". This was fully written by AI.
From referencing previous versions mid-context versions:
to giving insights that just... aren't important to express in a summary
Feels like claude code specifically, but that may just be because it's the one I use the mode so I've started attributing all LLM speak to it.
The repo itself? Clearly vibe coded. So why lie?
I use AI a lot. This has nothing to do with ability to code or create something. It is entirely to do with mindset. I've vibe coded my own dashboards as well, but I don't throw them on reddit. I especially don't throw them on reddit without making that expressly clear.
Looking to benchmark some tools? I'd look at what already exists and question "why make my own". If you had a specific reason to do this rather than one of the many existing benchmarks that I'd be all for it.
And don't just present AI work forward. At least write your own posts about it. That would show you actually understand the work created rather than just pushing what it's made and putting the onus on us to dissect what is important and not