52 FastAPI interview questions with detailed answers, sorted from basic to advanced. Free to practice, with progress saved automatically.
FastAPI is a Python framework for building APIs that uses type hints and Pydantic to validate data and generate interactive documentation. The questions cover Pydantic models and serialization, dependency injection, OAuth and JWT security, database sessions, what happens when blocking code runs inside an async endpoint, project structure, error handling, testing, and deployment.
and 9 more topics.
FastAPI is a Python framework for building HTTP APIs, based on type hints, Starlette and Pydantic. You declare data types once, and FastAPI uses them to validate requests, convert types and generate OpenAPI docs. Send {"age": "20"} and age is converted to the number 20;…
A path operation is a function bound to an HTTP method and path, such as GET /users/{id} or POST /orders. FastAPI reads function type hints to parse path params, query params, body, headers, cookies and validate automatically. The decorator @app.get("/users/{id}") declares the method (GET) and…
Pydantic models define schemas for request bodies, responses, settings or intermediate objects. FastAPI uses them to validate input, serialize output and generate OpenAPI schemas. The parameter payload: UserCreate is a Pydantic model, so FastAPI treats it as a JSON request body. If the client omits…
FastAPI builds an OpenAPI schema (a JSON file describing the whole API) from the code you already wrote, with no separate declaration. The schema is served at /openapi.json, and the two docs pages read from it: Swagger UI at /docs and ReDoc at /redoc. From…
FastAPI distinguishes them from the declaration position and type of each parameter: - Path param: the name appears in the path template, like userid in /users/{userid}. - Query param: a simple type (int, str, bool) that is not in the path. The value comes after…
responsemodel enforces the declared output schema: it validates/serializes responses, filters fields that should not be exposed and generates accurate OpenAPI. Example avoiding password hash leaks: Do not rely on a handler accidentally omitting sensitive fields; make the response schema an explicit protection layer.
A FastAPI dependency is a callable declared with Depends or Security. FastAPI calls the dependency, passes required request params, caches the result within the request if reused, and injects the result into the handler. Example: With a yield dependency, code before yield runs before the…
A dependency with yield fits resources that need setup/cleanup such as database sessions, transactions, file handles or external clients. Code before yield runs before the handler, the yielded value is injected into the handler, and code after yield runs when the request finishes (by default…
APIRouter groups routes by feature/module and lets you set shared prefix, tags, dependencies and responses. The root app includes the router with app.includerouter(). Example: Large apps should split by domain such as users, orders, billing, not by technical layer with every controller in one file.
PATCH should use a separate model with optional fields, then apply only fields sent by the client. With Pydantic v2, modeldump(excludeunset=True) distinguishes missing fields from fields explicitly sent as null. Example: changes contains only the fields the client actually sent. Sending {"bio": "new"} changes only…
FastAPI splits errors into two groups. Validation errors (wrong type, missing field) are caught by Pydantic, and FastAPI returns 422 with the list of failing fields without any code from you. Business errors (out of stock, user not found) are detected in your own code,…
Common pattern: a login endpoint verifies credentials and issues a short-lived access token; protected endpoints use a dependency to read the Bearer token, verify signature/expiry, load the user and inject currentuser. Short dependency example (using PyJWT: pip install pyjwt, import jwt): jwt.decode raises when the…
CORS is configured with CORSMiddleware. Do not use wildcard origins with credentials in production; whitelist concrete domains per environment. Example: CORS is only a browser policy, not an API security boundary. The backend must still authenticate and authorize requests.
Each request should have its own session scope, usually created with a yield dependency. Services/repositories receive the session through dependency injection or function parameters. Commit/rollback should live in one fixed place: either the service calls commit() after a business operation, or a dependency wraps the…
BackgroundTasks runs a task after the response has been sent, fitting lightweight work such as sending email, writing audit logs or non-critical webhooks. It is not a replacement for a real queue. Example: If the task needs retry, scheduling, durability or long execution, use Celery/RQ/Arq,…
Middleware wraps the whole request/response cycle and fits cross-cutting concerns such as request ids, logging, timing, CORS, compression, trusted hosts or security headers. Timing middleware example: Do not put business logic in middleware because it lacks route-level domain context and is harder to test.
Lifespan manages app-level resources such as connection pools, cache clients, ML models or schedulers. Code before yield runs at startup; code after yield runs at shutdown, so resources open and close with the app lifecycle. Example: Do not create heavy resources at global import time…
TestClient works with every endpoint, including async def ones: it runs the app in its own event loop, while the test stays a plain function with no await. Only when the test function itself must await something else (e.g. query an async DB to check…
Tests must never touch the production database. Use a separate test database of the same type as production (if production is PostgreSQL, test on PostgreSQL, because SQLite differs in data types and locking). To start every test from a clean state, the common approach is…
ASGI (Asynchronous Server Gateway Interface) is the standard for how a web server and a Python app talk to each other: the server handles networking (opening the port, reading bytes from the socket), turns each request into data in a standard format and calls the…
For FastAPI in Docker, optimize three things: a small image that builds fast (use the layer cache), safety (do not run as root), and behaving well under an orchestrator (receive signals for graceful shutdown, choose how many processes per container). Each point in the file…
FileResponse is for a file that already exists on disk: FastAPI reads it in small chunks and sets the headers for you. StreamingResponse is for content that is not ready yet or is too large to hold in memory: you pass a generator, and each…
SSE (Server-Sent Events) is an HTTP response that never closes: the server keeps writing events like data: ... into that same response, and the client only listens. WebSocket starts as an HTTP request with an Upgrade header, then the connection switches to its own protocol…
bytes reads the whole file into memory and only fits small files. UploadFile uses a spooled file (kept in RAM up to about 1 MB, written to a temporary file on disk beyond that), includes metadata such as filename/contenttype and supports async reads, fitting larger…
Use pydantic-settings (split out of Pydantic as a separate package in v2) to parse environment variables with types, defaults and validation. In Pydantic v2, BaseSettings is imported from pydanticsettings and configured via modelconfig = SettingsConfigDict(...). Settings should be injected via dependency or created as an…
There are two ways to split directories. By layer groups files by technical role: all routers in one place, all services in another. By feature groups files by business area: each domain (users, orders) has its own router, service and schemas. Layers are easy to…
Status codes should reflect API outcomes: 200 for successful read/update, 201 for create, 204 for delete/no content, 400 for semantic input errors, 401 unauthenticated, 403 forbidden, 404 missing resource, 409 conflict, and 422 for requests with wrong types or missing fields. Example: FastAPI returns 422…
Liveness answers "can the process still run". If it fails, the orchestrator such as Kubernetes restarts the container. Readiness answers "is the app ready to take requests". If it fails, the orchestrator stops sending traffic to that instance but does not restart it. Kubernetes treats…
The whole event loop is blocked for the duration of the HTTP wait, so every other request served by that process queues up behind it. Reason: an async def function runs directly on the event loop. The loop only switches work at await points. A…
Annotated puts Depends in the type position rather than in the default-value position. FastAPI has recommended it since 0.95.0, and Ruff ships rule FAST002 to flag the old form. Three practical wins: - Type is preserved → editors and mypy still see user as User…
Use responsemodelexcludeunset=True on the path operation decorator. FastAPI then serializes the model with excludeunset, dropping every field that was not explicitly assigned when the object was built. Two related options: - responsemodelexcludenone=True — drop fields whose value is None (different from excludeunset: a field explicitly…
No. --reload is a development-only flag: it watches files and restarts the process, costing CPU and hurting stability. Production runs multiple worker processes instead. With the FastAPI CLI the equivalent is fastapi run --workers 4. The old uvicorn.workers.UvicornWorker class is deprecated and now lives in…
Starlette hands def functions to a threadpool via anyio.tothread.runsync, so synchronous code does not block the event loop. That pool is bounded: AnyIO defaults to 40 threads per process. Under load this means request 41 onward queues for a free thread — latency climbs, requests…
No. FastAPI caches dependency values per request: if several dependencies share getsettings, that function runs once and the result is reused across every branch of that request. Here getdbuser hits the DB once even though it is declared twice. The cache key is the (dependency…
fromattributes=True in modelconfig lets Pydantic v2 read an object's attributes (an ORM object) instead of only dict keys or instances of the model itself (v1 called this ormmode). Without it, UserOut.modelvalidate(ormuser) raises an error. There are two different situations. When an endpoint declares responsemodel and…
fieldvalidator checks one field; modelvalidator checks relationships between fields — for example enddate must follow startdate, or "at least one of two phone numbers is required". mode decides when it runs relative to Pydantic coercion: - mode='before': runs before coercion, receiving raw input. Use it…
TestClient is a synchronous client: it spins up its own event loop to run the app, so the test body cannot await other async code (calling an async repository, asserting against an async DB). AsyncClient with ASGITransport keeps the test in the same event loop…
Return a StreamingResponse backed by a generator that reads in batches, instead of building the whole file in memory and sending it at once. Each iteration keeps a single row in buffer and then clears it, so memory does not grow with the row count.…