Search Topics
Search across all FastAPI topics
Background Tasks
Core ConceptYour user waited 5 seconds for a signup that should have taken 200ms. Let's fix that.
A user signs up. Your endpoint sends a welcome email synchronously. The SMTP server takes 5 seconds to respond. The user stares at a loading spinner for 5 seconds just to see "Registration successful".
POST /signup {"email": "alice@example.com", "name": "Alice"}
# Server timeline:
# 0.0s — Receive request
# 0.1s — Create user in DB ✓
# 0.2s — Start sending welcome email...
# 5.2s — Email sent ✓
# 5.2s — Return response
# User waited 5.2 seconds for a 0.1-second operation.
# Response time: 5,200ms (should be ~200ms)Question
Think about it: the user's account was created in 100ms. Everything after that — the email, the logging, the admin notification — the user doesn't need to wait for any of it. So why are you making them?
The Idea: Respond First, Work Later
Background tasks let you send the response immediately and do the slow stuff after the user has already moved on. Here's the flow:
Request arrives
POST /signup
Create user
~100ms
Queue tasks
Email, logging...
Send response
User sees success!
Run tasks
After response sent
the core concept
What you just learned
Background tasks run AFTER the response is sent — the user never waits
You queue tasks during request handling, but they execute after the response
Perfect for emails, logging, notifications — anything the user doesn't need to see immediately
Your First Background Task
FastAPI has this built in. Just inject BackgroundTasks and add functions to it. They'll run after the response is sent.
from fastapi import BackgroundTasks, FastAPI
app = FastAPI()
def send_email(email: str, message: str):
# This could take 5 seconds — doesn't matter!
# The user already got their response.
print(f"Sending email to {email}: {message}")
@app.post("/signup")
async def signup(email: str, background_tasks: BackgroundTasks):
# Step 1: Do the fast stuff
# create_user(email) # ~100ms
# Step 2: Queue the slow stuff
background_tasks.add_task(send_email, email, "Welcome!")
# Step 3: Respond immediately
return {"message": "User created, email will be sent"}
# ← Response goes out NOW. Email sends AFTER.Insight
Notice the function signature: background_tasks: BackgroundTasks. FastAPI sees that type hint and automatically injects the background task manager. You don't create it yourself. Just declare it and use it.
Queuing Multiple Tasks
You can queue as many tasks as you want. They run sequentially in the order you added them — one finishes, the next starts.
def write_log(message: str):
with open("log.txt", "a") as f:
f.write(f"{message}\n")
def notify_admin(user_email: str):
send_email("admin@example.com", f"New signup: {user_email}")
@app.post("/signup")
async def signup(email: str, background_tasks: BackgroundTasks):
# Queue them up — they run in this order AFTER response
background_tasks.add_task(send_email, email, "Welcome!")
background_tasks.add_task(write_log, f"New user: {email}")
background_tasks.add_task(notify_admin, email)
return {"message": "Signup complete"}
# User gets this instantly. Three tasks run behind the scenes.basic background tasks
What you just learned
add_task() takes a function and its arguments — the function runs after the response
Multiple tasks run sequentially in the order they were added
The response time is now independent of how many background tasks you queue
Go Deeper: Tasks in Dependencies
Here's something neat: your dependencies can also queue background tasks. FastAPI uses the same BackgroundTasks instance across your endpoint and all its dependencies.
async def log_request(
background_tasks: BackgroundTasks,
q: str | None = None,
):
if q:
# This dependency queues a background task
background_tasks.add_task(write_log, f"Query: {q}")
@app.get("/items")
async def list_items(
background_tasks: BackgroundTasks,
q: str | None = Depends(log_request),
):
# Your endpoint adds its own task too
background_tasks.add_task(write_log, "Items listed")
return items
# Both tasks run after the response — dep's task firstWatch out
Background tasks run in the same process as your API. If a background task hogs the CPU or crashes, it can affect your API's performance. For heavy workloads (processing videos, sending thousands of emails), use a proper task queue like Celery or Dramatiq instead.
See It: Background Task Flow
Watch how FastAPI sends the response immediately, then runs email, logging, and notification tasks in the background — the client never waits.
Think about it...
If a background task raises an exception after the response was already sent, does the user see a 500 error?
Hint: Think about the timeline: when does the response leave vs when does the task run?
Key Points
After Response
Tasks run after the response is sent — no client waiting
Sequential
Multiple tasks run in the order they were added
In-Process
Runs in the same process — use Celery for heavy workloads
Use Cases
Email, logging, cache invalidation, webhook notifications