Built-in Background Tasks: Simple and Effective

Built-in Background Tasks: Simple and Effective

Send emails and process data without waiting. Learn how to use FastAPI's native BackgroundTasks system to improve user response times.

Built-in Background Tasks: Simple and Effective

In a professional API, you never make a user wait for a process that they don't need an immediate answer to. If a user signs up, they need an immediate "Welcome" page, but they don't need to wait 5 seconds for your server to connect to an external email provider to send the confirmation email.

In this lesson, we learn about FastAPI's built-in BackgroundTasks system.


1. The Problem: Response Latency

Imagine an endpoint that processes an image and sends an email.

@app.post("/signup")
async def signup(user_data: UserCreate):
    save_to_db(user_data) # 10ms
    send_welcome_email(user_data.email) # 2000ms (Slow!)
    return {"message": "Success"}

Total Wait Time: 2+ seconds. This is a bad user experience.


2. The Solution: BackgroundTasks

BackgroundTasks is a simple class provided by FastAPI. You add a function to it, and FastAPI will run that function after it has already sent the response back to the user.

from fastapi import BackgroundTasks

def send_email_task(email: str):
    # Logic to send email
    print(f"Email sent to {email}")

@app.post("/signup")
async def signup(user_data: UserCreate, tasks: BackgroundTasks):
    save_to_db(user_data)
    
    # Add to the queue
    tasks.add_task(send_email_task, user_data.email)
    
    # This return happens IMMEDIATELY
    return {"message": "Success! Email is being sent."}

3. How it Works (Under the Hood)

FastAPI runs background tasks using the same Event Loop as your application.

  • Pros: Zero setup, no extra servers needed (unlike Celery).
  • Cons: Since it uses the same process, if you perform a massive CPU-heavy calculation, it might slow down your main API.

When to use Built-in Tasks:

  • Sending Emails.
  • Logging data to a secondary database.
  • Small clean-up tasks.

4. Injecting Dependencies into Tasks

One major benefit of built-in tasks is that they have access to the same environment as your routes. You can even pass database sessions or shared services into them easily.


Visualizing the Background Flow

sequenceDiagram
    participant U as User
    participant A as FastAPI App
    participant T as Background Worker
    
    U->>A: POST /signup
    A-->>U: 200 OK (Instant Feedback)
    A->>T: Run send_email_task()
    Note right of T: Process continues in background

Summary

  • Response Speed: Background tasks are the #1 way to make an API feel "Snappy."
  • add_task: Use it to register functions to run after the response is sent.
  • Limits: Use built-in tasks for light I/O work (emails, simple logs).

In the next lesson, we’ll look at Task Queues (Celery and Redis) for heavy industrial workloads.


Exercise: The Log Finisher

You want to log every "Password Change" to a separate security file.

  1. Create a function log_security_event(username: str).
  2. Show how you would use BackgroundTasks to call this function in a /change-password route so the user doesn't wait for the file write.

Subscribe to our newsletter

Get the latest posts delivered right to your inbox.

Subscribe on LinkedIn