FastAPI hỗ trợ cả async def và def thường cho path operation. Lựa chọn quan trọng về hiệu năng: dùng async def khi bạn có thể await I/O non-blocking, và dùng thường khi code của bạn gọi các thao tác blocking (đồng bộ).
FastAPI hỗ trợ cả async def và def thường cho path operation. Lựa chọn quan trọng về hiệu năng: dùng async def khi bạn có thể await I/O non-blocking, và dùng thường khi code của bạn gọi các thao tác blocking (đồng bộ).
def@app.get("/async")
async def async_endpoint():
data = await fetch_from_api() # await I/O non-blocking — hiệu quả
return data
@app.get("/sync")
def sync_endpoint():
data = blocking_db_call() # code blocking thông thường
return data
async def → chạy trên event loop chính. Chỉ hiệu quả NẾU bạn await các lời gọi non-blocking.
⚠️ Một lời gọi BLOCKING bên trong async def chặn TOÀN BỘ event loop → giết tính đồng thời!
def → FastAPI chạy nó trong một THREAD POOL, nên code blocking không chặn event loop.
An toàn cho các thư viện đồng bộ/blocking.
# ✅ async def — khi bạn có thể await thư viện async (httpx, async DB driver)
async def get_user():
async with httpx.AsyncClient() as c:
return await c.get(url)
# ✅ def thường — khi dùng thư viện ĐỒNG BỘ/blocking (requests, sync ORM)
def get_user():
return requests.get(url).json() # blocking → FastAPI chạy nó trong một thread
# ❌ SAI LẦM NGUY HIỂM — lời gọi blocking bên trong async def
async def bad():
return requests.get(url).json() # chặn event loop! Dùng `def` hoặc một async client
Quy tắc then chốt: không bao giờ đặt lời gọi blocking trong async def — nó chặn event loop và phá hủy tính đồng thời. Hoặc dùng thư viện async với await, hoặc dùng def thường (mà FastAPI chạy an toàn trong thread pool).
Chọn đúng giữa async def và def ảnh hưởng trực tiếp đến hiệu năng và tính đồng thời của API, và làm sai là một sai lầm phổ biến, nghiêm trọng.
Hiểu biết then chốt là async def chỉ có lợi khi bạn await các thao tác non-blocking — đặt một lời gọi blocking (như thư viện requests đồng bộ hay một database driver blocking) bên trong async def chặn toàn bộ event loop, đóng băng mọi request đồng thời và làm hỏng mục đích của async.
Ngược lại, FastAPI khéo léo chạy các endpoint def thường trong một thread pool, nên code đồng bộ/blocking an toàn ở đó.
Hiểu quy tắc này — dùng async def với thư viện thực sự async, dùng def thường cho code blocking, và không bao giờ trộn lời gọi blocking vào async def — là thiết yếu để viết endpoint FastAPI hiệu năng và tránh sai lầm tinh vi nhưng tàn khốc là vô tình tuần tự hóa mọi request sau một event loop bị chặn.