The Problem
When using ContextMiddleware, background tasks execute after the middleware's context manager has already exited and reset the context. While Python's ContextVar inheritance (PEP 567) might make context appear available in background tasks, this is an implementation detail and is not guaranteed.
The Recommended Pattern: Explicit Context Passing
To ensure reliability, you must capture a copy of the context data during the request and pass it explicitly as an argument to your background task function.
Do not attempt to call context.get() directly inside a background task function.
from fastapi import FastAPI, BackgroundTasks
from starlette_context import context
from starlette_context.middleware import ContextMiddleware
app = FastAPI()
app.add_middleware(ContextMiddleware)
def process_item(item_id: str, context_data: dict):
# ✅ RECOMMENDED: Use explicitly passed context data
# This is reliable and guaranteed to work
print(f"Processing item {item_id} with context: {context_data}")
request_id = context_data.get("X-Request-ID")
@app.post("/items/{item_id}")
async def create_item(item_id: str, background_tasks: BackgroundTasks):
# Capture context data during request
context_data = context.data.copy()
# Pass context data explicitly to the background task
background_tasks.add_task(process_item, item_id, context_data)
return {"message": "Item will be processed"}