lesson depth
Mastery
not started · 0%

FastAPI Custom ASGI Middleware

Request processing chains, correlation IDs, ContextVars, and response header mutation.

Freshness: current14 min readComputer Science and Programming

Key Learning Outcomes

  • Build custom ASGI HTTP middlewares
  • Track correlation IDs safely with ContextVars

Mental model

FastAPI middleware is an outer ASGI wrapper around your application, executing onion-style before and after every HTTP request.

HTTP Request
Outer ASGI Middleware
Trace Correlation ID ContextVar
FastAPI Router & Route Handler
Response Header Mutation
Conceptual teaching model synthesized from:FastAPI Framework Architecture & Dependency Injection Specification

Theory

Custom middlewares can be implemented via @app.middleware("http") or pure ASGI class wrappers (BaseHTTPMiddleware). Middlewares are ideal for cross-cutting concerns: setting unique X-Request-ID correlation headers, logging request duration, handling global CORS policies, and scoping thread-safe request state using Python contextvars.ContextVar.

python(28 lines)
1import time
2import uuid
3from contextvars import ContextVar
4from fastapi import FastAPI, Request
5
6request_id_var: ContextVar[str] = ContextVar("request_id", default="")
7
8app = FastAPI()
9
10@app.middleware("http")
11async def add_correlation_id_and_timing(request: Request, call_next):
12 correlation_id = request.headers.get("X-Request-ID", str(uuid.uuid4()))
13 token = request_id_var.set(correlation_id)
14
15 start_time = time.perf_counter()
16 response = await call_next(request)
17 duration_ms = (time.perf_counter() - start_time) * 1000
18
19 response.headers["X-Request-ID"] = correlation_id
20 response.headers["X-Process-Time-MS"] = f"{duration_ms:.}"
21
22 request_id_var.reset(token)
23 return response
24
25@app.get("/health")
26async def health_check():
27 return {"status": "ok", "correlation_id": request_id_var.get()}
8 lines hidden

Alternatives and trade-offs

  • Middlewares: Run globally on every request (CORS, timing, request ID).
  • FastAPI Dependencies: Run only on targeted routes and support Depends graph composition.

Failure modes and misconceptions

  1. BaseHTTPMiddleware Streaming Issues: BaseHTTPMiddleware buffers responses in memory and can break SSE / WebSocket streaming.
  2. ContextVar Leaks: Always reset ContextVar tokens in finally blocks when reusing threads across requests.
Reflect before revealing the guide

Decision scenario

Use @app.middleware("http") for application-wide request logging and correlation headers. Use route-level Depends for granular authentication and authorization checks.

Learning outcomes

  • Build HTTP middlewares for correlation tracing and latency logging.
  • Store context-local state safely across async tasks using contextvars.ContextVar.
  • Avoid response buffering issues with high-throughput streaming endpoints.

Trade-offs

Global middlewares execute on every incoming HTTP request path, so middleware logic must stay extremely fast and lightweight.

Prerequisites & Related Concepts (2)

Private notes

0 words
Next