Skip to main content

Getting Started with Background Tasks

In this tutorial, you will learn how to use the BackgroundTasks class to perform operations after a response has been sent to the client. This is useful for tasks like sending emails, processing files, or logging data where the user doesn't need to wait for the operation to complete.

Prerequisites

To follow this tutorial, you need to have the fastapi package installed. The examples below use Python 3.10+ type annotations.

Step 1: Define the Background Task

First, create a function that performs the work you want to run in the background. This can be a standard def function or an async def function.

In this example, we define a function that writes a notification message to a file:

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

Step 2: Register the Task in a Path Operation

To schedule the task, you must declare a parameter of type BackgroundTasks in your path operation function. FastAPI will provide an instance of this class automatically.

Use the .add_task() method to register your function and its arguments:

from fastapi import BackgroundTasks, FastAPI

app = FastAPI()

def write_notification(email: str, message=""):
with open("log.txt", mode="w") as email_file:
content = f"notification for {email}: {message}"
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="some notification")
return {"message": "Notification sent in the background"}

When you call this endpoint, FastAPI will:

  1. Execute the send_notification function.
  2. Send the JSON response {"message": "Notification sent in the background"} to the client.
  3. After the response is sent, execute the write_notification function.

Step 3: Use Background Tasks in Dependencies

FastAPI also allows you to use BackgroundTasks inside dependencies. This is powerful because it allows multiple parts of your request logic to contribute to the background task queue. FastAPI ensures that the same BackgroundTasks object is shared across the entire request.

Here is how you can inject BackgroundTasks into a dependency:

from fastapi import BackgroundTasks, Depends, FastAPI

app = FastAPI()

def write_log(message: str):
with open("log.txt", mode="a") as log:
log.write(message)

def get_query(background_tasks: BackgroundTasks, q: str | None = None):
if q:
message = f"found query: {q}\n"
background_tasks.add_task(write_log, message)
return q

@app.post("/send-notification/{email}")
async def send_notification(
email: str, background_tasks: BackgroundTasks, q: str = Depends(get_query)
):
message = f"message to {email}\n"
background_tasks.add_task(write_log, message)
return {"message": "Message sent"}

In this example:

  1. The get_query dependency adds a task to log the query parameter if it exists.
  2. The send_notification path operation adds another task to log the email message.
  3. Both tasks are added to the same BackgroundTasks instance and will run sequentially after the response is sent.

How it Works

The BackgroundTasks class (found in fastapi/background.py) inherits from starlette.background.BackgroundTasks.

When you use .add_task(func, *args, **kwargs), FastAPI stores the function and its arguments. If the function is a standard def, FastAPI runs it in a separate threadpool so it doesn't block the main event loop. If it is an async def, FastAPI awaits it directly.

Next Steps

  • Use BackgroundTasks for non-critical side effects like analytics or cleanup.
  • For heavy computational tasks or long-running processes, consider using a dedicated task queue like Celery, as BackgroundTasks runs within the same process as your FastAPI application.