FastAPI is a Python web framework for building HTTP APIs on top of Starlette (ASGI) and Pydantic. Type hints on endpoint parameters drive request parsing, validation, serialisation and the generated OpenAPI schema, so one declaration does the work that other frameworks spread across decorators, schemas and documentation.
async and await, FastAPI handles high-performance asynchronous endpoints, ideal for high concurrency.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
# Define the application
app = FastAPI()
# Define a request model with Pydantic
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
# Define a simple POST endpoint
@app.post("/items/")
async def create_item(item: Item):
return {"name": item.name, "price_with_tax": item.price + (item.tax or 0)}
/items/ POST endpoint accepts Item data, validates it, and calculates the price_with_tax.FastAPI combines simplicity and power, making it a strong choice for modern REST API development.
FastAPI is an ASGI application, so it runs under an ASGI server such as Uvicorn or Hypercorn rather than a WSGI server. The server hands the raw request to Starlette, which runs middleware (CORS, GZip, custom timing) and matches the path to a route. FastAPI then resolves the endpoint's dependencies, parses path, query, header and body parameters according to their type hints, and validates the body with Pydantic. Only if everything validates is your function called. Its return value is checked against the declared response_model, converted to JSON-compatible data and sent back.
Endpoints may be declared with async def or plain def. Async endpoints run on the event loop and must not block it; synchronous endpoints are run in a thread pool automatically. Mixing in a blocking database driver inside an async def endpoint is the most common performance mistake. Under load, run several Uvicorn worker processes (or Gunicorn with the Uvicorn worker class) behind a reverse proxy such as Nginx or Apache, so that CPU-bound work in one request does not delay all others and a crashed worker is restarted automatically.
Depends() declares that a parameter is produced by another function. Dependencies can depend on other dependencies, forming a graph that FastAPI resolves per request, caching each result so a shared dependency such as a database session is created only once. A dependency written as a generator with yield can run cleanup code after the response is sent, which is the idiomatic way to close sessions and release locks. Because dependencies are ordinary functions, tests can replace them with app.dependency_overrides.
from fastapi import FastAPI, Depends, HTTPException, Header, status
from pydantic import BaseModel, Field
app = FastAPI(title="Inventory API")
DB: dict[int, dict] = {}
class ItemIn(BaseModel):
name: str = Field(min_length=1, max_length=100)
price: float = Field(gt=0)
class ItemOut(ItemIn):
id: int
def require_token(x_api_key: str = Header()):
if x_api_key != "secret-demo-key":
raise HTTPException(status.HTTP_401_UNAUTHORIZED, "bad key")
return x_api_key
@app.post("/items", response_model=ItemOut, status_code=201)
def create_item(item: ItemIn, _: str = Depends(require_token)):
new_id = len(DB) + 1
DB[new_id] = item.model_dump()
return {"id": new_id, **DB[new_id]}
@app.get("/items/{item_id}", response_model=ItemOut)
def read_item(item_id: int):
if item_id not in DB:
raise HTTPException(404, "not found")
return {"id": item_id, **DB[item_id]}
pip install "fastapi[standard]"
uvicorn main:app --reload
curl -X POST localhost:8000/items -H "X-API-Key: secret-demo-key" \
-H "Content-Type: application/json" -d '{"name":"pen","price":1.5}'
curl localhost:8000/items/1
# interactive docs: http://localhost:8000/docs
Posting {"price": -1} returns 422 with an error for each failing field, without any validation code in the endpoint. The X-API-Key header is mapped from the parameter name x_api_key. The example uses Pydantic v2 (model_dump); on Pydantic v1 the method is dict().
| Framework | Strengths | Choose when |
|---|---|---|
| FastAPI | Typed validation, OpenAPI docs, async | JSON APIs, ML model serving, microservices |
| Flask | Small, mature, synchronous, huge ecosystem | Simple services, server-rendered pages |
| Django + DRF | ORM, admin, auth, batteries included | Large apps with a relational data model |
FastAPI is a good fit when the API contract matters and clients benefit from a generated schema. It provides less out of the box than Django: no ORM, admin or migrations, so you choose SQLAlchemy or another library yourself, and assemble migrations and admin tooling separately.
async def stalls every concurrent request; use def or async libraries.response_model can leak fields such as password hashes.Compare with Flask and GraphQL, and see Implementing an API for general design guidance.