FastAPI soporta tanto async def como def regular para operaciones de ruta. La elección importa para el rendimiento: usa async def cuando puedas await I/O no-bloqueante, y regular cuando tu código realiza operaciones bloqueantes (síncronas).
FastAPI soporta tanto async def como def regular para operaciones de ruta. La elección importa para el rendimiento: usa async def cuando puedas await I/O no-bloqueante, y regular cuando tu código realiza operaciones bloqueantes (síncronas).
def@app.get("/async")
async def async_endpoint():
data = await fetch_from_api() # await non-blocking I/O — efficient
return data
@app.get("/sync")
def sync_endpoint():
data = blocking_db_call() # ordinary blocking code
return data
async def → runs on the main event loop. Efficient ONLY if you await non-blocking calls.
⚠️ A BLOCKING call inside async def blocks the WHOLE event loop → kills concurrency!
def → FastAPI runs it in a THREAD POOL, so blocking code doesn't block the event loop.
Safe for synchronous/blocking libraries.
# ✅ async def — when you can await async libraries (httpx, async DB drivers)
async def get_user():
async with httpx.AsyncClient() as c:
return await c.get(url)
# ✅ plain def — when using SYNCHRONOUS/blocking libraries (requests, sync ORM)
def get_user():
return requests.get(url).json() # blocking → FastAPI runs it in a thread
# ❌ THE DANGEROUS MISTAKE — blocking call inside async def
async def bad():
return requests.get(url).json() # blocks the event loop! Use `def` or an async client
La regla crítica: nunca pongas llamadas bloqueantes en async def — bloquea el event loop y destruye la concurrencia. O usa una librería async con await, o usa un def simple (que FastAPI ejecuta de forma segura en un thread pool).
Elegir correctamente entre async def y def afecta directamente el rendimiento y la concurrencia de tu API, y cometer un error es un equívoco común y grave.
La insight clave es que async def solo es beneficioso cuando haces await de operaciones no-bloqueantes — poner una llamada bloqueante (como la librería síncrona requests o un driver de base de datos bloqueante) dentro de un async def bloquea todo el event loop, congelando todas las solicitudes concurrentes y derrotando el propósito de async.
Por el contrario, FastAPI inteligentemente ejecuta endpoints def simples en un thread pool, así que el código síncrono/bloqueante es seguro allí.
Entender esta regla — usa async def con librerías verdaderamente async, usa def simple para código bloqueante, y nunca mezcles llamadas bloqueantes en async def — es esencial para escribir endpoints FastAPI performantes y evitar el error sutil pero devastador de serializar accidentalmente todas las solicitudes detrás de un event loop bloqueado.