backend / web frameworks / fastapi / 10_fastapi_async.md

FastAPI

3 interview angles 2 min read source

FastAPI

What is FastAPI and why use it for async backends?

FastAPI is a modern Python web framework for building APIs. It’s built on ASGI (async), so you can define async route handlers and use await for I/O (DB, HTTP, etc.) without blocking the event loop. Benefits: high throughput for I/O-bound work, automatic OpenAPI docs, request validation via Pydantic, and native dependency injection with Depends(). It’s a good fit for async backends and microservices.


How do you define async vs sync route handlers in FastAPI?

  • Async: async def my_endpoint(): ... — FastAPI runs it on the event loop; you can await inside. Use for async I/O (async DB, HTTP clients).
  • Sync: def my_endpoint(): ... — FastAPI runs it in a thread pool so it doesn’t block the loop. Use for CPU-bound or legacy blocking code.

Prefer async when you have async libraries; use sync for blocking code and let FastAPI run it in a thread.


What is Depends() and how is it used?

Depends() is FastAPI’s dependency injection mechanism. You declare a dependency (a function or callable) in the route signature; FastAPI calls it and injects the return value. Used for: shared DB sessions, auth (get current user), config, and reusable logic. Dependencies can depend on other dependencies. FastAPI builds the dependency graph and injects at request time.


How does FastAPI relate to the event loop?

FastAPI is an ASGI application. The server (e.g. Uvicorn) runs an event loop and passes each request to the app. Async route handlers run as coroutines on that loop; when they await, the loop can serve other requests. So FastAPI doesn’t create the loop—the ASGI server does—but your async endpoints run in that loop. Blocking calls in an async handler block the whole loop; use async libraries or run blocking code in an executor.

Interview angle

  • “What happens if you use a sync database driver in an async def route?” - it blocks the event loop for the duration, stalling every other request in that worker. Either use an async driver, or declare the route as plain def so FastAPI runs it in the threadpool.
  • “Is the threadpool unlimited?” - no. It’s bounded, so many concurrent blocking routes will queue. That queueing shows up as latency with no obvious CPU or database pressure.
  • “How do you run concurrent calls inside one handler?” - asyncio.TaskGroup (or gather) with per-call timeouts, so total latency is the slowest call rather than the sum. See ../../04_async_concurrency/12_taskgroup_structured_concurrency.md.