FastAPI obsługuje zarówno async def jak i zwykły def dla operacji ścieżek. Wybór ma znaczenie dla wydajności: użyj async def gdy możesz nie-blokujący I/O, a zwykły gdy twój kod wywołuje operacje blokujące (synchroniczne).
FastAPI obsługuje zarówno async def jak i zwykły def dla operacji ścieżek. Wybór ma znaczenie dla wydajności: użyj async def gdy możesz nie-blokujący I/O, a zwykły gdy twój kod wywołuje operacje blokujące (synchroniczne).
awaitdef@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
Krytyczna reguła: nigdy nie umieszczaj blokujących wywołań w async def — blokuje pętlę zdarzeń i niszczy współbieżność. Albo użyj biblioteki async z await, albo użyj zwykłego def (który FastAPI bezpiecznie uruchamia w puli wątków).
Poprawny wybór między async def i def bezpośrednio wpływa na wydajność i współbieżność twojego API, a wybór nieprawidłowy jest częstym i poważnym błędem.
Klucz do zrozumienia to fakt, że async def jest korzystny tylko gdy awaitasz operacje nie-blokujące — umieszczenie blokującego wywołania (takiego jak synchroniczna biblioteka requests lub sterownik blokującego bazy danych) wewnątrz async def blokuje całą pętlę zdarzeń, zamraża wszystkie współbieżne żądania i niweluje cel async.
Z drugiej strony, FastAPI sprytnie uruchamia zwykłe endpointy def w puli wątków, więc kod synchroniczny/blokujący jest tam bezpieczny.
Zrozumienie tej reguły — użyj async def z naprawdę asynchronicznymi bibliotekami, użyj zwykłego def do kodu blokującego, i nigdy nie mieszaj blokujących wywołań w async def — jest niezbędne do pisania wydajnych punktów końcowych FastAPI i unikania subtelnego ale niszczącego błędu przypadkowej serializacji wszystkich żądań za zamrożoną pętlę zdarzeń.