FastAPI Middleware and Background Tasks

FastAPI middlewares runs fantastically with ordinary requests, yet it might not execute background tasks.

It is a known issue that the BaseHTTPMiddleware cannot be used with BackgroundTasks.

(Read Limitations section in the doc)

However, FastAPI only guides solutions that using BaseHTTPMiddleware class, by using app.middleware decorator like below.

from fastapi import FastAPI, Request

app = FastAPI()

async def some_middleware(request: Request, call_next):
    # some logic here
    return await call_next(request)

The decorator above uses BaseHTTPMiddleware under the hood, just like below:

# starlette/
def middleware(self, middleware_type: str) -> typing.Callable:
    def decorator(func: typing.Callable) -> typing.Callable:
        self.add_middleware(BaseHTTPMiddleware, dispatch=func)
        return func

    return decorator

In order to create a middleware but to guarantee execution of the background tasks, use pure middleware instead.

Pure Middleware

starlette docs introduces how to create a pure ASGI middleware.

In case creating a pure middleware with typing, example codes looks like below:

from starlette.types import ASGIApp, Scope, Receive, Send
from starlette.middleware import Middleware

class RequestPrintMiddleware:
    """Request Scope Print Middleware"""

    def __init__(self, app: ASGIApp) -> None: = app

    async def __call__(
        self, scope: Scope, receive: Receive, send: Send
    ) -> None:
        # Add logics here
        await, receive, send)

Don’t forget to register the middleware.

from starlette.middleware import Middleware

middlewares = [Middleware(RequestPrintMiddleware)]
app = FastAPI(middleware=middlewares)

app.add_middleware cannot be used, since Middleware cannot be asigned to the parameter middleware_class.

So you have to pass list of middlewares to middleware parameter, when you initiate app instance, just like the code provided above.