Lower Your Response Time: Background Tasks in FastAPI

At the heart of every high-performance project is a clean code that doesn't let unnecessary processes get in the way of maintaining a low response time. If you use FastAPI, then your emphasis on developing high-performance APIs should not be undermined by the time-consuming tasks that a user doesn't need to wait for. In this article, we will discuss an efficient way of handling the FastAPI processes that lowers your response time, sends some of the processes to the background, and makes a seamless flow for your project.

What are FastAPI Background Tasks?

FastAPI Background tasks are operations that run after you have returned a response. Why perform operations after a response? Good question. Some operations are done in case of receiving a user request, but the user doesn't necessarily need to wait for them to complete before they receive their response.

Why Use Background Tasks?

You may be asking yourself what scenarios you need FastAPI background tasks for.
For example, if your user is asking to change their password and you want to send them a link, your user doesn't need to wait until you generate the link and send it until they receive their response. As soon as the process of generating and sending the link is triggered, you can return the response.
Another example is when the user sends you a file that needs to be processed. Let's say the user has uploaded a picture that needs to be scanned for graphic content before you set it as their profile picture. In this case, you can send the user a response like HTTP 202 (i.e., the "Accepted" response) and do the image processing later.

How to Use FastAPI Background Tasks

First, you will need to import BackgroundTasks from the FastAPI library:

from fastapi import BackgroundTasks, FastAPI

Next, one of the path operation functions needs to have a BackgroundTasks object as the input:

@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
    # ...

This way, FastAPI will automatically create a BackgroundTasks object and pass it onto your function when there is a request. Note that the path operation function must be defined as async.

Next, you use the background_tasks instance to trigger the function of another function in the background while you immediately return the "accepted" response to the user. You have to do this using an add_task function that is an attribute of background_tasks. Here's how it looks:

background_tasks.add_task(write_notification, email, message="some notification")

This other function that will run in the background doesn't need to be an async or await function, and can be a normal def based on its usage.

The final result will look like this:

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"}

And just like that, you're done!

Note that this is a simple usage of the background tasks and more detailed work–including dependency injection–is possible and explained on the FastAPI website.

Conclusion

In this article, we talked about the FastAPI background tasks, when they are needed, and how they are used.

If you still haven't checked my blog, check it out! I post about programming and Linux.

← Back