Problem
Distributed tracing across 15+ microservices was broken. Developers were supposed to pass correlation IDs in every request, but they kept forgetting. Some services generated their own IDs, others didn't pass them at all.
Key Insight
Infrastructure concerns belong in infrastructure layers. Injecting correlation IDs in HTTP middleware means app code never touches them:
@app.middleware("http")
async def correlation_middleware(request, call_next):
correlation_id = request.headers.get(
"X-Correlation-ID", str(uuid4())
)
# Attach to request state + response headers
request.state.correlation_id = correlation_id
response = await call_next(request)
response.headers["X-Correlation-ID"] = correlation_id
return responseAfter this change, 100% of requests had correlation IDs. Zero developer effort required.
Takeaway
Don't rely on developers remembering to do infrastructure tasks. Make it the path of least resistance — automatic, invisible, and impossible to skip.