FastAPI поддерживает как async def, так и обычный def для операций пути. Выбор влияет на производительность: используйте async def когда вы можете неблокирующий I/O, и обычный когда ваш код вызывает блокирующие (синхронные) операции.
FastAPI поддерживает как async def, так и обычный def для операций пути. Выбор влияет на производительность: используйте async def когда вы можете неблокирующий I/O, и обычный когда ваш код вызывает блокирующие (синхронные) операции.
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
Критическое правило: никогда не помещайте блокирующие вызовы в async def — это блокирует event loop и уничтожает параллелизм. Либо используйте асинхронную библиотеку с await, либо используйте простой def (который FastAPI безопасно запускает в thread pool).
Правильный выбор между async def и def напрямую влияет на производительность и параллелизм вашего API, и ошибка здесь — это частая и серьёзная проблема.
Ключевое понимание заключается в том, что async def полезен только когда вы awaitите неблокирующие операции — помещение блокирующего вызова (например, синхронной библиотеки requests или блокирующего драйвера базы данных) внутрь async def блокирует весь event loop, замораживает все параллельные запросы и уничтожает смысл асинхронности.
Наоборот, FastAPI умно запускает простые def эндпойнты в thread pool, поэтому синхронный/блокирующий код там безопасен.
Понимание этого правила — использование async def с по-настоящему асинхронными библиотеками, использование простого def для блокирующего кода, и никогда не смешивание блокирующих вызовов в async def — необходимо для написания производительных эндпойнтов FastAPI и избежания тонкой, но разрушительной ошибки случайной сериализации всех запросов позади заблокированного event loop.