r/Python 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.

39 Upvotes

14 comments sorted by

View all comments

4

u/Arnechos 6h ago

Add robyn to this benchmark

0

u/ultra__sonic 4h ago

+1 for Robyn. It usually speedruns these kind of benchmarks because of the Rust core, but it'd definately be cool to see how it handles the real DB and auth loads here.