Async vs def in FastAPI: Key Differences and Usage Guide
async in FastAPI when your endpoint performs I/O-bound operations like database calls or network requests to improve concurrency. Use def for CPU-bound or simple synchronous code where async is unnecessary.Quick Comparison
This table summarizes the main differences between using async and def in FastAPI endpoints.
| Factor | async | def |
|---|---|---|
| Function Type | Asynchronous coroutine function | Synchronous regular function |
| Use Case | I/O-bound tasks (DB, HTTP calls) | CPU-bound or simple sync tasks |
| Concurrency | Allows other tasks to run during await | Blocks until function completes |
| Performance | Better for many simultaneous requests | Simpler, less overhead for sync code |
| Syntax | Must use await inside | No await allowed |
| Compatibility | Requires async-compatible libraries | Works with any Python code |
Key Differences
FastAPI supports both async and def endpoint functions, but they behave differently under the hood. An async function is a coroutine that can pause its execution at await points, allowing FastAPI to handle other requests concurrently. This is especially useful when your endpoint calls external services like databases or APIs, which are I/O-bound and can take time to respond.
On the other hand, a def function runs synchronously and blocks the server until it finishes. This is fine for CPU-bound tasks or simple logic that does not involve waiting for external resources. Using async unnecessarily for CPU-heavy work can add overhead without benefits.
Also, async endpoints require that any libraries you call inside support asynchronous operations. If you use synchronous libraries inside an async function without proper handling, it can block the event loop and reduce performance.
Code Comparison
from fastapi import FastAPI import asyncio app = FastAPI() @app.get("/async") async def read_async(): await asyncio.sleep(1) # Simulate I/O-bound wait return {"message": "Async response after 1 second"}
def Equivalent
from fastapi import FastAPI import time app = FastAPI() @app.get("/sync") def read_sync(): time.sleep(1) # Simulate blocking CPU-bound wait return {"message": "Sync response after 1 second"}
When to Use Which
Choose async when:
- Your endpoint performs I/O-bound operations like database queries, HTTP requests, or file operations.
- You want to handle many requests concurrently without blocking the server.
- You use async-compatible libraries that support
await.
Choose def when:
- Your code is CPU-bound or simple synchronous logic without waiting.
- You use synchronous libraries that do not support async.
- You want simpler code without async overhead.
Using the right function type improves FastAPI app performance and responsiveness.
Key Takeaways
async for I/O-bound tasks to improve concurrency in FastAPI.def for CPU-bound or simple synchronous code.