FastAPI, minus the slow.
A fork of FastAPI 0.141.1 that does less work per request: the same public API and test suite, with the plain JSON route down from 31.2 to 18.3 µs on uvicorn and 9.1 µs on granian.
Site: https://notslowapi.com
Docs: https://notslowapi.com/docs/
Source: https://github.com/4thel00z/notslowapi
Install
uv add notslowapi[granian]
pip install "notslowapi[granian]"
Python 3.10 to 3.14 and pydantic>=2.9.0. Pydantic v1 is not supported. The base install brings no ASGI server; the granian extra adds granian>=2.0. The standard extra is FastAPI's and pulls the same set upstream does. Nothing is installed under the fastapi or starlette names, and existing installs of those packages are left alone.
Switch
from notslowapi import FastAPI
Replace the package name fastapi with notslowapi in every import. The modules upstream exposes under fastapi.* exist under notslowapi.*: responses, requests, middleware, security, openapi, encoders, exceptions, background, staticfiles, templating, testclient, websockets, sse, status.
Run
granian --interface asgi --workers 1 --loop uvloop myapp:app
myapp:app is the module path and attribute of your FastAPI instance. granian's I/O runs on Rust threads alongside the Python thread, so the framework's Python is the only thing left on the critical path. On a bare ASGI callable the server alone costs 7.8 µs per request under granian against 13.5 µs under uvicorn, and the notslowapi route adds 1.3 µs on top of that under granian against 4.8 µs under uvicorn.
On uvicorn, install uvicorn[standard] for uvloop and httptools (18.3 µs on the plain route against 64.0 µs on asyncio and h11) and run:
uvicorn myapp:app --loop uvloop --http httptools --no-proxy-headers --no-server-header --no-date-header
Leave --proxy-headers on if a proxy in front of you sets X-Forwarded-* headers and your app reads them.
Numbers
One core (Apple M3 Pro, Python 3.13), 64 keep-alive connections, median of 3 x 5 s oha runs, one worker. The first column is upstream FastAPI 0.141.1 on uvicorn at the start of the work; the other two are notslowapi 0.1.0. Raw files: bench/baseline/results_ladder_v1.json and results_ladder_v3.json in the repository.
| route | day one, uvicorn (FastAPI 0.141.1) | notslowapi, uvicorn | notslowapi, granian |
|---|---|---|---|
| raw ASGI app, fixed bytes (server floor) | 13.7 µs, 73,040 req/s | 13.5 µs, 74,172 req/s | 7.8 µs, 128,801 req/s |
| plain JSON route | 31.2 µs, 32,033 req/s | 18.3 µs, 54,793 req/s | 9.1 µs, 110,154 req/s |
| int path + str query param | 57.0 µs, 17,531 req/s | 24.2 µs, 41,405 req/s | 14.3 µs, 69,742 req/s |
| pydantic body + response_model | 52.1 µs, 19,212 req/s | 26.1 µs, 38,295 req/s | 20.1 µs, 49,777 req/s |
| 50 routes via include_router | 92.2 µs, 10,800 req/s * | 26.3 µs, 37,968 req/s | 17.3 µs, 57,864 req/s |
* This rung did not exist in results_ladder_v1.json. The 92.2 µs is the before-run of the include_router change (bench/baseline/results_fix11_before.json), measured on a tree that already had the first ten changes, so it understates the day-one gap.
The changes are inside the framework: parameter extraction, the dependency solver, routing, exception handling and response encoding. Each is one commit with a before and after measurement, listed at What changed. The method, the tools and the raw files are at Benchmark method; the full tables are at notslowapi.com/benchmarks/.
Compatibility
notslowapi 0.1.0 has the public API of FastAPI 0.141.1: classes, functions, parameters and behaviors are upstream's, and the changes are internal. The check is the upstream test suite with its imports rewritten: 3,335 FastAPI tests plus 1,154 Starlette tests, 4,489 pass, with the same 8 environmental failures before and after every change. The modified Starlette 1.6.0 ships inside the package as notslowapi.starlette and nothing is installed under the starlette name, so code that imports starlette.* directly needs upstream Starlette installed and gets upstream behavior for those objects.
from notslowapi.starlette.middleware.base import BaseHTTPMiddleware
from notslowapi.starlette.responses import Response
Two observable differences: AsyncExitStackMiddleware is importable but no longer installed, so the scope no longer carries fastapi_middleware_astack, and solve_dependencies raises RuntimeError instead of failing an assert when a yield dependency runs without an exit stack. Details at Compatibility.
Reporting a regression
Open an issue at github.com/4thel00z/notslowapi/issues with the notslowapi version, a minimal app, and what FastAPI 0.141.1 does with the same code. For a performance regression, name the machine, Python version and server, and attach bench/out/results.json from a before and an after run of the ladder.
Credits
notslowapi is built from FastAPI by Sebastián Ramírez and Starlette by Encode. The code is theirs; this fork changes how much of it runs per request. FastAPI's documentation applies to notslowapi with the package name swapped.
License
The FastAPI code is MIT licensed, copyright 2018 Sebastián Ramírez (LICENSE). The vendored Starlette is BSD-3-Clause, copyright 2018 Encode OSS Ltd (notslowapi/starlette/LICENSE.md). Both files ship in the wheel; the package metadata declares MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file notslowapi-0.1.0.tar.gz.
File metadata
- Download URL: notslowapi-0.1.0.tar.gz
- Upload date:
- Size: 546.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6501afbb9d89154eff2567add78c083c5091c5e444eff7ccf387123c61197eb1
|
|
| MD5 |
6d051da6ed2860b7cf8e816ece9725fb
|
|
| BLAKE2b-256 |
1f866bce2e7f1330c5135be5e0e88d947a1afa1f865bcfa091db0cd9aa0601bf
|
Provenance
The following attestation bundles were made for notslowapi-0.1.0.tar.gz:
Publisher:
release.yml on 4thel00z/notslowapi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
notslowapi-0.1.0.tar.gz -
Subject digest:
6501afbb9d89154eff2567add78c083c5091c5e444eff7ccf387123c61197eb1 - Sigstore transparency entry: 2694389666
- Sigstore integration time:
-
Permalink:
4thel00z/notslowapi@50bb5725e5269bd26c325a56666353f83c7029d0 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/4thel00z
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@50bb5725e5269bd26c325a56666353f83c7029d0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file notslowapi-0.1.0-py3-none-any.whl.
File metadata
- Download URL: notslowapi-0.1.0-py3-none-any.whl
- Upload date:
- Size: 211.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9362e642ca0f33a8e69b25b0d3dd7fbbead5e56a55f0291c5d3d9149d69264e0
|
|
| MD5 |
6ae5d0e98818cef22800ff8f51c3606f
|
|
| BLAKE2b-256 |
9aae9d331f94438a28662101f667e0c22ff08a67412c56af246b41d9681ff696
|
Provenance
The following attestation bundles were made for notslowapi-0.1.0-py3-none-any.whl:
Publisher:
release.yml on 4thel00z/notslowapi
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
notslowapi-0.1.0-py3-none-any.whl -
Subject digest:
9362e642ca0f33a8e69b25b0d3dd7fbbead5e56a55f0291c5d3d9149d69264e0 - Sigstore transparency entry: 2694389763
- Sigstore integration time:
-
Permalink:
4thel00z/notslowapi@50bb5725e5269bd26c325a56666353f83c7029d0 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/4thel00z
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@50bb5725e5269bd26c325a56666353f83c7029d0 -
Trigger Event:
push
-
Statement type: