What is FastAPI¶
FastAPI is a Python web framework for building APIs, created by Sebastián Ramírez and first released in December 2018. It is open source under the MIT license. Its selling points are that you declare your API with ordinary Python type hints, and in return you get automatic request validation, serialization, and interactive API documentation — with performance on par with Node.js and Go, because it runs on ASGI (async) rather than WSGI (sync).
If you come from Django, the single most important thing to understand up front is this: FastAPI is not a Django-sized framework. It is a thin, focused layer that does routing, validation, and documentation, and leaves everything else — the database, the admin, templates, auth — to libraries you choose and wire together yourself.
FastAPI is a stack, not a monolith¶
Installing Django gives you one coherent thing that does almost everything. FastAPI is deliberately small and stands on two other libraries:
- Starlette — the ASGI toolkit underneath. It provides the actual HTTP handling: routing, requests and responses, middleware, background tasks, WebSockets, and the test client. FastAPI is a Starlette application with extra features layered on top. Anything Starlette can do, a FastAPI app can do.
- Pydantic — data validation and serialization from type hints. Every request body, query parameter, and response shape is a Pydantic model or a type Pydantic understands.
FastAPI itself contributes the type-hint magic that ties these together: it reads your function signatures, wires up validation via Pydantic and routing via Starlette, and generates an OpenAPI schema for free.
To actually serve requests you also need an ASGI server — most commonly Uvicorn. That's the equivalent of the WSGI server (Gunicorn/uWSGI) you already run Django behind in production, except it speaks the async ASGI protocol.
From Django: Django is "batteries included" — ORM, migrations, admin, auth, forms, templates, sessions, and the WSGI handler all ship in one package with one release cycle. FastAPI is the opposite: it owns routing + validation + docs, and for everything else you assemble a stack. There is no
django-admin startprojectthat lays down a settings module, a URL conf, and a WSGI entry point. You start from an empty file.
What ships, and what you bring yourself¶
| Concern | Django | FastAPI |
|---|---|---|
| URL routing | urls.py + path() |
decorators on functions (@app.get(...)) |
| Request validation | Forms / DRF serializers | Pydantic models (built in) |
| Serialization | DRF serializers / templates | Pydantic + response_model (built in) |
| Interactive API docs | DRF Browsable API / add-on | Swagger UI + ReDoc (built in) |
| ORM | Django ORM (built in) | none — bring SQLAlchemy, SQLModel, Tortoise, … |
| Migrations | Django migrations (built in) | none — bring Alembic (or your ORM's tool) |
| Admin site | django.contrib.admin (built in) |
none — bring SQLAdmin, Piccolo, or build one |
| Auth / sessions | django.contrib.auth (built in) |
none — bring OAuth2/JWT helpers, Depends |
| Templates | Django Template Language (built in) | none built in — Starlette + Jinja2 |
| Settings | settings.py module |
none — bring pydantic-settings |
| Server | WSGI (ASGI optional) | ASGI (Uvicorn) |
The empty cells on the FastAPI side are the whole reason this book has a "From Django's batteries to a FastAPI stack" topic near the end: moving to FastAPI is partly learning the framework and partly learning which library replaces each Django battery you took for granted.
The type-hint idea in 10 lines¶
Here is a complete FastAPI application. It validates input, serializes output, and documents itself — all from the type hints.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
From those hints FastAPI infers that:
item_idcomes from the path and must be anint—/items/abcreturns a422validation error, not a crash.qis an optional query string —/items/5?q=helloworks, so does/items/5.- the returned
dictis serialized to JSON.
Run it with Uvicorn and open /docs:
pip install "fastapi[standard]==0.139.2" "uvicorn==0.34.0"
uvicorn main:app --reload
# open http://127.0.0.1:8000/docs
You get a live Swagger UI where you can call the endpoint, plus a second
docs UI at /redoc, both generated from the same OpenAPI schema.
From Django: The closest Django-world analogue is Django REST Framework, where you declare a
Serializerand get validation plus a Browsable API. FastAPI collapses that into the function signature itself — the parameter is the schema. And where DRF's schema/OpenAPI generation is an add-on you configure, in FastAPI the OpenAPI document and the two doc UIs are on by default from the first line.
ASGI vs WSGI: why "async" is the headline¶
WSGI — the protocol Django was built on — is synchronous: one request
occupies one worker thread/process until it finishes. ASGI is the async
successor. It lets a single worker handle many in-flight requests
concurrently by suspending them at await points (waiting on a database,
an HTTP call, a queue) instead of blocking a whole thread.
FastAPI is ASGI-native. You write path operations as either def
(regular, run in a threadpool) or async def (run on the event loop),
and mixing them is fine:
@app.get("/sync")
def sync_view():
return {"style": "sync"}
@app.get("/async")
async def async_view():
return {"style": "async"}
From Django: Django is WSGI-first but has supported ASGI and
async defviews for several versions, so async isn't unique to FastAPI. The practical difference is default and depth: FastAPI is async all the way down (Starlette, the test client, dependencies, middleware), whereas in Django large parts of the stack — most notably much of the ORM — are still synchronous, so anasync defview often ends up callingsync_to_asyncaround blocking pieces. We devote a whole topic to this later.
Stewardship, versioning, and stability¶
- Developed in the open at github.com/fastapi/fastapi.
- MIT licensed; primarily maintained by Sebastián Ramírez and a team of maintainers, funded through sponsorships.
- Pre-1.0. FastAPI is versioned
0.x. In practice it is widely used in production and quite stable, but it does not follow semantic versioning yet: a minor version bump (e.g.0.138→0.139) can include a breaking change. Pin an exact version (fastapi==0.139.2) and read the release notes before upgrading.
From Django: This is a real culture shift. Django's Sixth-release compatibility guarantees and LTS branches mean you can lean on a version for years. FastAPI moves faster and asks you to pin and track more actively — and because your stack is several independently versioned libraries (FastAPI, Starlette, Pydantic, Uvicorn, your ORM), "the framework version" is really a set of versions you manage together.
Community and resources¶
- fastapi.tiangolo.com — the official docs; the tutorial is excellent and doubles as a reference.
- docs.pydantic.dev and starlette.io — you will read these directly, since FastAPI hands real work to both.
- The FastAPI GitHub Discussions, the
r/FastAPIsubreddit, and the large Pydantic/SQLAlchemy communities you'll draw the rest of your stack from.