Skip to main content

FastAPI Background Tasks Introduction

What are Background Tasks?

Background tasks allow you to execute operations "in the background" after returning a response to the client. This is extremely useful when you need to perform operations that don't need to be completed before sending a response.

In web applications, you often need to perform operations that might take some time but aren't critical for the immediate response. For instance:

  • Sending confirmation emails
  • Processing uploaded files
  • Updating database statistics
  • Triggering notifications
  • Cleanup operations

Why Use Background Tasks?

Using background tasks offers several benefits:

  1. Improved Response Time: Your API can return responses faster since time-consuming tasks run afterward.
  2. Better User Experience: Users don't have to wait for non-essential operations to complete.
  3. Resource Efficiency: Long-running tasks don't block your application from handling other requests.

How FastAPI Implements Background Tasks

FastAPI provides a simple yet powerful way to run background tasks using the BackgroundTasks class. This approach is lighter than Celery or other full task queue systems but offers enough functionality for many common use cases.

Let's learn how to use it!

Basic Background Task Example

Here's a simple example of using background tasks in FastAPI:

python
from fastapi import FastAPI, BackgroundTasks

app = FastAPI()

def write_notification(email: str, message=""):
with open("log.txt", mode="a") as email_file:
content = f"notification for {email}: {message}\n"
email_file.write(content)

@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
background_tasks.add_task(write_notification, email, message="Hello World")
return {"message": "Notification sent in the background"}

In this example:

  1. We define a function write_notification that writes to a file.
  2. We create an endpoint that accepts an email address.
  3. We add the write_notification function as a background task.
  4. The endpoint returns a response immediately, while the background task runs afterward.

When you call this endpoint, you'll get an immediate response, and the file writing happens in the background.

Input and Output Example

Request:

POST /send-notification/[email protected]

Response:

json
{
"message": "Notification sent in the background"
}

And the log.txt file will contain:

notification for [email protected]: Hello World

How Background Tasks Work in FastAPI

When you add a background task in FastAPI, this is what happens:

  1. FastAPI processes the request and generates a response
  2. The response is sent back to the client
  3. After sending the response, FastAPI executes the background tasks in the order they were added
  4. If a background task raises an exception, FastAPI logs the error but continues with other tasks

It's important to note that background tasks run in the same process as FastAPI. They don't run in a separate process or thread by default.

Multiple Background Tasks

You can add multiple background tasks that will be executed in order:

python
from fastapi import FastAPI, BackgroundTasks

app = FastAPI()

def write_log(message: str):
with open("log.txt", mode="a") as file:
file.write(f"{message}\n")

def send_email(email: str, message: str):
# Email sending simulation
with open("emails.txt", mode="a") as file:
file.write(f"Email to {email}: {message}\n")

@app.post("/process/{email}")
async def process(email: str, background_tasks: BackgroundTasks):
# Add multiple background tasks
background_tasks.add_task(write_log, f"Processing request for {email}")
background_tasks.add_task(send_email, email, "Your request is being processed")

return {"status": "Processing started"}

Real-World Example: Image Processing

Here's a more practical example. Imagine you're building an API that allows users to upload images that need to be processed (resized, compressed, etc.):

python
from fastapi import FastAPI, UploadFile, BackgroundTasks, File
import shutil
import time
from pathlib import Path
import uuid

app = FastAPI()

def process_image(image_path: str):
# Simulate image processing with a delay
time.sleep(3)

# In a real app, you might use Pillow or another library to process the image
processed_dir = Path("processed")
processed_dir.mkdir(exist_ok=True)

# Simulating the processing result
with open(f"processed/{Path(image_path).name}", "w") as f:
f.write(f"Processed content for {image_path}")

print(f"Image {image_path} has been processed")

@app.post("/upload-image/")
async def upload_image(background_tasks: BackgroundTasks, image: UploadFile = File(...)):
# Generate a unique filename
filename = f"{uuid.uuid4()}-{image.filename}"
upload_dir = Path("uploads")
upload_dir.mkdir(exist_ok=True)

file_path = f"uploads/{filename}"

# Save uploaded image
with open(file_path, "wb") as buffer:
shutil.copyfileobj(image.file, buffer)

# Add image processing as background task
background_tasks.add_task(process_image, file_path)

return {
"filename": filename,
"status": "Image uploaded successfully. Processing started in background."
}

This example shows how you can:

  1. Accept a file upload
  2. Save the file to the server
  3. Start processing it in the background
  4. Return an immediate response to the user

The user doesn't have to wait for the processing to complete before getting a response.

Best Practices for Background Tasks

  1. Keep them short and simple: Background tasks in FastAPI run in the same process, so very long-running or resource-intensive tasks might still affect your application's performance.

  2. Handle exceptions: Always implement proper error handling in background tasks since exceptions won't be returned to the client.

python
def background_task_with_error_handling():
try:
# Your task logic here
process_data()
except Exception as e:
# Log the error
print(f"Background task error: {e}")
# You might want to store errors in a database or send alerts
  1. For complex workloads, consider other solutions: If you need more sophisticated task processing (retries, scheduling, distributed processing), consider using dedicated task queues like Celery, RQ, or Dramatiq.

Summary

FastAPI's background tasks provide a simple and effective way to perform operations after sending a response to the client. They're perfect for operations like:

  • Sending emails
  • Light data processing
  • Updating non-critical records
  • Generating reports
  • Cleanup operations

For more complex scenarios requiring task queues, schedulers, or distributed processing, you may need to integrate FastAPI with more advanced task processing systems.

Additional Resources

  1. FastAPI official documentation on background tasks
  2. Starlette background tasks documentation (FastAPI is built on Starlette)
  3. Celery Project for more advanced task queue requirements

Exercises

  1. Create a FastAPI endpoint that accepts a message and sends it as an email in the background.
  2. Modify the image processing example to generate thumbnails of different sizes in the background.
  3. Create an endpoint that records user activity in a database using background tasks.
  4. Implement a system that uses background tasks to clean up temporary files older than a day.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)