FastAPI interview question · Most asked

When should an endpoint be `async def` versus plain `def` in FastAPI?

Summary

Use async def when the endpoint only awaits async I/O (async DB drivers, httpx). Use plain def when it calls blocking libraries, because FastAPI runs def endpoints in a threadpool so they don't block the event loop.

Longer Answer

The danger is calling blocking code (e.g., requests.get, time.sleep, sync SQLAlchemy, CPU-heavy work) inside async def. That freezes the event loop for every concurrent request. Options: switch to async libraries, make the endpoint def, or offload with await run_in_threadpool(func) / anyio.to_thread.run_sync. CPU-bound work belongs in a process pool or a task queue.

Code Example

import httpx
from fastapi.concurrency import run_in_threadpool

@app.get("/weather")
async def weather(city: str):
    async with httpx.AsyncClient(timeout=5) as client:  # non-blocking
        r = await client.get(f"https://api.example.com/w?city={city}")
    return r.json()

@app.get("/legacy")
def legacy_report():  # sync def: runs in threadpool
    return blocking_sdk.generate()

@app.get("/mixed")
async def mixed():
    data = await run_in_threadpool(blocking_sdk.generate)
    return data

Key Points

  • async def + only non-blocking awaits
  • def endpoints run in a threadpool (default ~40 threads)
  • Never block inside async def
  • CPU-bound → process pool / Celery

Explanation

What interviewers look for

Clear explanation of the event loop blocking problem; this is the #1 FastAPI production pitfall.

Common mistakes

  • Using requests inside async def
  • Assuming async def makes code faster automatically

More most-asked FastAPI questions

← All FastAPI questions