FastAPI
FastAPI is the Python web framework behind the backends here. It is built on Starlette for the ASGI layer and Pydantic for validation, and its defining idea is deriving behaviour from type hints rather than from configuration.
One declaration, four consequences
Annotate an endpoint’s parameters and return type, and you get request parsing, validation with precise errors, response serialisation, and an OpenAPI schema — from the same declaration, with no separate schema definition to keep synchronised.
That last item is what matters most. The generated schema is what makes generated frontend clients possible, and that removes the whole class of frontend-backend contract drift. The chain — type hints produce validation, validation produces a schema, the schema produces a typed client — is the strongest argument for the framework, and it is more consequential than the speed the name emphasises.
The alternative in most frameworks is declaring types twice: once for validation, once for documentation, with nothing enforcing agreement. Here there is one declaration and no opportunity to drift.
Dependency injection
Depends is the second thing worth understanding. A dependency is a function whose result is injected into an endpoint, with results cached per request and dependencies able to depend on each other.
It is how authentication, database sessions, and permission checks compose without repetition. A get_current_user dependency that parses the JWT and loads the user is written once and declared by every endpoint needing it — and because it is an ordinary function, it can be overridden in tests with something returning a fixture user, which makes testing authenticated endpoints straightforward rather than a mocking exercise.
The async trap
FastAPI is ASGI-based and async throughout, and this is where people get hurt.
A blocking call inside an async def endpoint blocks the entire event loop — not just that request, but every concurrent request the process is handling. A synchronous database driver, requests, or any CPU-heavy work inside an async endpoint converts a concurrent server into a serial one under load, with no error to indicate it.
The rules are simple and easy to violate by accident: use async libraries inside async def, or define the endpoint as a plain def and let FastAPI run it in a threadpool. Mixing them is the common mistake, usually by calling one synchronous library inside an otherwise async handler. Anything genuinely long-running belongs in Celery regardless.
See also: Pydantic, SQLModel, client generation, JWT authentication, and Status Alganize.