← Back to blog

FastAPI interview questions and answers

FastAPI interview questions and answers guide — cover from Greenroom, the AI mock interviewer

"So you made the endpoint async," the interviewer said, "and it got slower under load. Why?" The candidate had no idea. Inside that endpoint was a plain requests.get() — a blocking call sitting in the event loop, holding up every other request on the worker while it waited. Making it async had removed the one thing that was saving him: the threadpool.

That is the single most-asked idea in FastAPI interview questions, and it catches experienced people because the framework makes the wrong thing look right. This guide covers the async model, dependency injection, Pydantic, background work and testing — with the follow-up behind each.

What FastAPI interviews actually test

FastAPI interview questions show up in Python backend, platform and ML-serving loops. Five bands:

  • The async modeldef vs async def, the event loop, blocking calls. The band that decides the round.
  • Dependency injectionDepends, scoping, overrides for testing.
  • Pydantic — validation, request vs response models, and what v2 changed.
  • Production concerns — background tasks, middleware, lifespan, workers, deployment.
  • TestingTestClient, async tests, dependency overrides.
FastAPI interview question topics diagram — the async model, dependency injection, Pydantic validation, production concerns, testing
The five bands of FastAPI interview questions, with the async model deciding most rounds.

async def vs def: the question from the intro

FastAPI treats the two differently, and knowing exactly how is the highest-value thing in this interview:

  • async def — runs directly on the event loop. Correct when the work is genuinely awaitable I/O: httpx, an async database driver, asyncio.sleep. Any blocking call inside it stalls the entire loop for every concurrent request.
  • Plain def — FastAPI runs it in an external threadpool, so blocking work does not stall the loop. This is why a synchronous endpoint using requests behaves fine while an async one using the same library falls over.

So the rule to state plainly: if your handler blocks, use def; if it awaits, use async def. The wrong combination — blocking code inside async def — is the worst case and the one interviewers describe.

import anyio, httpx
from fastapi import FastAPI

app = FastAPI()

# WRONG: blocking client inside async — stalls the event loop for everyone
@app.get("/bad")
async def bad():
    import requests
    return requests.get("https://api.example.com/x").json()

# RIGHT: awaitable client, so the loop is free while we wait on the network
@app.get("/good")
async def good():
    async with httpx.AsyncClient() as client:
        r = await client.get("https://api.example.com/x")
    return r.json()

# ALSO RIGHT: unavoidable blocking work pushed off the loop explicitly
@app.get("/cpu")
async def cpu():
    return await anyio.to_thread.run_sync(expensive_pure_python)

Follow-ups worth having ready: CPU-bound work does not belong on the event loop at all (thread it, or better, hand it to a task queue like Celery); and the GIL means threads help with I/O but not with CPU, which is why heavy computation needs processes or a separate service. Our Python interview questions guide covers the concurrency fundamentals underneath.

Dependency injection with Depends

FastAPI's DI system is its most distinctive feature, and interviewers probe whether you use it for more than database sessions. A dependency is any callable; FastAPI resolves it, caches it per request, and injects the result.

The points that score:

  • Caching is per request. The same dependency used by three sub-dependencies is evaluated once. Pass use_cache=False to opt out.
  • yield dependencies give you setup and teardown — open a database session, yield it, close it afterwards even if the handler raised. This is the standard session pattern.
  • Dependencies nest, so get_current_user can depend on get_token which depends on settings, and FastAPI resolves the whole graph.
  • Router- and app-level dependencies apply to every route beneath them — the clean way to enforce auth across a whole router rather than decorating each endpoint.
  • app.dependency_overrides swaps a dependency in tests. This is the single best answer to "how do you test an endpoint that hits the database?"

Pydantic: validation, response models and v2

Pydantic is where FastAPI gets its automatic validation and OpenAPI docs. Expect questions on:

  • How the request body is parsed — a type-annotated Pydantic model parameter becomes the body; scalars become query parameters unless declared otherwise. Being able to state that rule cleanly is a common checkpoint.
  • response_model — it is not documentation, it filters the response. Returning an ORM object with a hashed_password field is safe if the response model omits it, and this is the standard answer to "how do you avoid leaking fields?"
  • Separate schemas per directionUserCreate (accepts a password), UserRead (never returns one), UserUpdate (all fields optional). Interviewers like candidates who separate these instead of reusing one model.
  • Validatorsfield_validator for one field, model_validator for cross-field rules like "end date must follow start date."
  • Pydantic v2 — a Rust core with a large speed improvement, and renames worth knowing: orm_mode became from_attributes, .dict() became .model_dump(), @validator became @field_validator.

Also know that validation errors return HTTP 422 by default, not 400, and be ready to say why (it is a semantically valid request that failed validation) and how to customise the handler.

Background tasks, middleware and lifespan

The production band. BackgroundTasks runs work after the response is sent — good for sending an email or writing an audit log. The critical caveat interviewers want: it runs in the same process, so if the process dies the work is lost, and it does not survive a deploy. For anything that must not be lost, use a real queue (Celery, RQ, Arq) with a durable broker. Saying that distinction unprompted is a strong signal, and the RabbitMQ interview questions guide covers the broker side.

On lifespan: the modern replacement for @app.on_event("startup"), an async context manager that sets up connection pools and ML models before serving and tears them down after. The classic question — "where do you load a machine learning model?" — is answered by lifespan, so it loads once per process rather than per request.

On middleware: know that it wraps every request for cross-cutting concerns (timing, correlation IDs, CORS), that ordering matters, and that heavy work in middleware taxes every endpoint. Know CORS specifically, since it is the most common practical question.

On deployment: FastAPI is ASGI, served by Uvicorn, usually behind Gunicorn with Uvicorn workers or in containers with multiple replicas. Workers are processes, so module-level state is not shared between them — a real bug when people cache in a global dict and see inconsistent results. Our Docker interview questions guide and Nginx interview questions guide cover the layers in front.

Testing and the comparison questions

Testing answers: TestClient (built on httpx) for synchronous tests, httpx.AsyncClient with ASGITransport for async ones, and dependency_overrides to swap the database for a test session or a fake. Mention a transactional fixture that rolls back after each test — it is the pattern real teams use.

Then the framework comparison, which is asked in almost every loop. Be fair rather than partisan: Django gives you an ORM, admin, auth and conventions out of the box — better for a content-heavy product with a small team, heavier if you only need an API. Flask is minimal and mature with a huge ecosystem, but you assemble validation, async and docs yourself. FastAPI gives async, automatic validation and OpenAPI docs from type hints, at the cost of a younger ecosystem and a genuine need to understand async to avoid the trap in the intro. Our Django and Flask guides cover the alternatives.

The docs, real projects, ChatGPT — where each fits

  • The official FastAPI documentation — genuinely one of the best docs in open source, and the async and dependency pages answer most interview questions directly.
  • The Pydantic v2 migration guide — short, and it covers the renames interviewers use to check whether you are current.
  • Building and load-testing one service — highest yield. Put a blocking call in an async endpoint, hit it with a load tool, and watch throughput collapse. That single experiment makes the core question unbluffable.
  • Full Stack FastAPI template repositories — good reference for project structure, testing setup and auth patterns.
  • GeeksforGeeks-style dumps — fine for definitions, weak for "why did it get slower?"
  • ChatGPT — good for generating boilerplate and reviewing code. It will not notice your requests call inside an async def and ask what happens under load.
  • Greenroom — the spoken layer. Ari, the AI interviewer, runs the round out loud and pushes the consequence follow-up when your answer stops at the API name. Fair tradeoff: Ari will not profile your service.
The core truth: FastAPI interviews are concurrency interviews wearing a framework badge. If you can explain why a plain def endpoint survives a blocking call and an async def one does not, you have answered the hardest question in most loops.

How to prepare for a FastAPI interview

  • Week 1: the async model. Build both endpoints from the code above, load-test them, and explain the threadpool behaviour aloud in ninety seconds.
  • Week 2: dependency injection — nested dependencies, yield teardown, router-level auth, and overrides in tests.
  • Week 3: Pydantic v2 and production concerns — separate schemas per direction, lifespan model loading, middleware, and a Celery hand-off for durable work.
  • Final week: rehearse the Django/Flask/FastAPI comparison neutrally, prepare one service you built explained end to end, and run two full spoken mocks.

Building the rest of the stack? The REST API interview questions guide covers API design, the RabbitMQ guide covers async work, the Nginx guide covers the reverse proxy, and the backend developer interview questions guide covers the wider loop.

Frequently asked questions

What are the most common FastAPI interview questions?

The most common questions cover the difference between async def and plain def endpoints and how FastAPI runs each, what happens when you put a blocking call inside an async endpoint, how the Depends dependency injection system works including yield teardown and caching, how Pydantic validates requests and how response_model filters responses, when BackgroundTasks is insufficient and you need a real queue, and how you test endpoints that depend on a database.

What is the difference between async def and def in FastAPI?

An async def endpoint runs directly on the event loop, which is correct when the work is genuinely awaitable I/O such as an async HTTP client or database driver. A plain def endpoint is run by FastAPI in an external threadpool, so blocking work inside it does not stall the loop. The rule is simple: if your handler blocks, use def; if it awaits, use async def. Blocking code inside async def is the worst case.

Why does putting requests.get() inside an async endpoint hurt performance?

requests is a blocking library, so calling it inside an async def endpoint blocks the event loop thread for the entire duration of the network call. Every other concurrent request served by that worker is stalled behind it, so throughput collapses under load. The fix is either to use an awaitable client such as httpx.AsyncClient, or to make the endpoint a plain def so FastAPI runs it in the threadpool.

How does Depends work in FastAPI?

Depends declares that a parameter should be produced by calling another function, which FastAPI resolves before invoking your endpoint. Results are cached per request, so a dependency shared by several sub-dependencies is evaluated once. Dependencies using yield provide setup and teardown, which is the standard database session pattern. They nest arbitrarily, can be attached at router or app level for auth, and can be swapped in tests with app.dependency_overrides.

What is response_model used for in FastAPI?

response_model does more than document the response — it filters and validates the outgoing data. If you return an ORM object containing sensitive fields such as a hashed password, declaring a response model that omits those fields prevents them from being serialised. This is why the common pattern is separate schemas per direction: one model that accepts a password on creation and a different model that never returns one.

When should you use BackgroundTasks versus Celery in FastAPI?

BackgroundTasks runs work in the same process after the response is sent, which suits fire-and-forget work you can afford to lose such as a non-critical email or an audit log. Because it shares the process, the work is lost if the process crashes or is replaced during a deploy, and it competes for the same resources. For anything that must not be lost, needs retries, or is CPU-heavy, use a real task queue such as Celery with a durable broker.

FastAPI rounds are concurrency conversations one follow-up in. Greenroom runs mock backend interviews out loud with Ari — performance follow-ups included — and scores structure, clarity and depth. Free to start. Curious how it works? See how AI mock interviews work.
Try free →