How to run background tasks in FastAPI without blocking the response
BackgroundTasks, add_task method, background task function, response before task, use cases, limitations vs Celery, task in dependency
Background Tasks in FastAPI
BackgroundTasks lets you schedule work to run after the response is already sent to the client. The response is not delayed. Use it for fire-and-forget operations: sending emails, writing logs, triggering webhooks.
Basic background task
from fastapi import BackgroundTasks, FastAPI
app = FastAPI()
def send_welcome_email(email: str):
# Runs after response is sent
print(f"Sending welcome email to {email}")
@app.post("/register/")
def register_user(email: str, background_tasks: BackgroundTasks):
# ... save user to DB ...
background_tasks.add_task(send_welcome_email, email)
return {"message": "Registered"}
FastAPI injects BackgroundTasks automatically. Call add_task with the function and its arguments. The function runs in the same process after the response is sent.
Background tasks in dependencies
def log_request(background_tasks: BackgroundTasks, path: str):
background_tasks.add_task(write_log, path)
@app.get("/items/", dependencies=[Depends(log_request)])
def list_items():
return []
BackgroundTasks can be injected into dependencies too, not just route handlers. The tasks accumulate and all run after the route completes.
Limitations
BackgroundTasks is in-process and in-memory. If the server restarts, pending tasks are lost. For durable task queues, retries, or distributed workers, use Celery with Redis or RabbitMQ instead.
