FastAPI Interview Questions
FastAPI interviews are async-correctness interviews with a validation layer attached. The framework makes it trivial to write an `async def` endpoint, and equally trivial to put a blocking call inside one — at which point every concurrent request on that worker suffers, with no error and no obvious cause. That single failure mode is the most-asked question in FastAPI loops.
The counterintuitive detail that separates candidates is that a plain `def` endpoint is sometimes the correct choice. FastAPI runs synchronous endpoints in a threadpool, so blocking work inside `def` does not stall the loop. Blocking work inside `async def` does. A candidate who declares every endpoint `async` because it looks modern has the mechanism backwards.
Written and reviewed by Sahil Srivastav
What the bar actually is
You should be able to decide between `def` and `async def` from the work the endpoint does rather than from style: `async def` when every I/O call in it is awaitable, plain `def` when it must call something blocking. And you should know the escape hatch — running blocking work in a threadpool executor — for when you need `async def` for other reasons.
On dependencies you are expected to understand lifecycle rather than just syntax: that a dependency with a `yield` runs teardown after the response, that this is where session and connection cleanup belongs, and that getting it wrong produces the pool exhaustion that is the second most common FastAPI production failure.
How the rounds are structured
Machine coding with FastAPI
A small API with validation and persistence. Expect probing on async choices and on where the database session is created and closed.
Async behaviour
What blocks the loop, `def` versus `async def`, how to measure loop lag, and why adding workers does not fix a blocking call.
Validation and schema design
Pydantic models at the boundary, separating request, response and database shapes, and what should be validated where.
Dependencies and lifecycle
Dependency scope, `yield` teardown, session management, and startup/shutdown handling for pools and clients.
What this interview bar tests
def versus async def, decided by the work
Synchronous endpoints run in a threadpool and may block safely. Blocking inside `async def` stalls every task on the loop. The decision follows from what the endpoint calls.
Session lifecycle in a dependency
A `yield` dependency gives you teardown after the response. Sessions created outside this discipline leak on exception paths, which is how pools get exhausted.
Distinct models at each boundary
Request, response and persistence shapes diverge. One shared model exposes internal fields and couples your API to your schema.
Measuring loop lag
Knowing how to detect a blocked loop rather than guessing. Candidates who name a measurement are immediately more credible.
A preparation plan that works
- 1Build two versions of one endpoint — a blocking call inside `async def`, and the same call in a plain `def` — and measure latency on an unrelated endpoint under load. The difference is the whole lesson.
- 2Write a database session as a `yield` dependency and then make the endpoint raise. Confirm teardown runs. Then do it wrong and watch the pool drain.
- 3Separate your request, response and ORM models for one resource and articulate what each boundary protects. Interviewers probe whether this is deliberate or accidental.
- 4Instrument loop lag on a small service so you can describe how you would detect blocking in production rather than only reason about it.
Questions you should expect
Should this endpoint be `def` or `async def`?
Decided by what it calls. If every I/O operation is awaitable — an async database driver, an async HTTP client — use `async def`. If it must call something blocking, a plain `def` is correct, because FastAPI runs synchronous endpoints in a threadpool where blocking is contained. Declaring `async def` and then blocking inside it is the worst of both.
Your async endpoint is slow and CPU is low. Why?
Something blocking is executing on the event loop — a synchronous driver, a `requests` call, or CPU-bound work — and while it runs no other task progresses. Latency rises on unrelated endpoints sharing the loop. Measure loop lag to confirm, then move the call to a threadpool executor or switch to an async client. Adding workers spreads the stall rather than removing it.
Where should the database session live?
In a dependency with `yield`, so teardown runs after the response on every path including exceptions. Creating a session inside the endpoint body and closing it at the end leaks whenever anything raises in between — and that leak is the usual cause of FastAPI pool exhaustion.
Should the request and response use the same Pydantic model?
No. They have different concerns: the request should reject fields a client must not set, and the response should exclude internal fields. Sharing one model with the ORM shape also couples your public API to your schema, so a column rename becomes a breaking change.
What gets candidates rejected
- Declaring every endpoint `async def` without regard to what it calls
- Blocking calls inside `async def`, then adding workers to compensate
- Creating database sessions in the endpoint body rather than a `yield` dependency
- One Pydantic model shared across request, response and persistence
- No way to detect a blocked event loop other than guessing
- Validation logic in the endpoint that Pydantic should enforce at the boundary
- Clients and pools created per request instead of at startup
What to practise, in order
Database connection pool exhaustion
Sessions leaked on exception paths — the exact failure that a `yield` dependency prevents, with tests asserting the lifecycle invariant.
API client pagination and retry
Paging an upstream API with retries that must not duplicate or skip records, including deadlines that actually abort in-flight calls.
Webhook event idempotency and ordering
The endpoint-level guarantee that makes client retries safe, with duplicates and reordering driven by the tests.
Full result materialization heap spike
An endpoint whose memory scales with total data rather than the page requested.
FAQ
Is FastAPI actually faster than Django or Flask?
For I/O-bound concurrency with async drivers throughout, meaningfully so. For CPU-bound work, no — the GIL still applies and the event loop makes it worse by serialising everything behind the blocking call. The honest answer names the workload rather than quoting a benchmark.
How much Pydantic depth is expected?
Validators, nested models, and clear separation of boundary shapes. Pydantic v2 changed validator syntax and performance characteristics, so know which version you have actually used — the follow-up usually gets specific.
Do I need an async ORM?
Only if you are going async end to end. A synchronous ORM inside `async def` is the classic blocking bug; the same ORM inside a plain `def` endpoint is entirely fine. Pick one model and be consistent rather than mixing by accident.
How should background work be handled?
`BackgroundTasks` for short, non-critical work that may be lost if the process restarts. Anything durable belongs in a real queue, because an in-process background task has no retry, no visibility and no persistence — a distinction interviewers probe deliberately.