How to Propagate Custom Context across Macroservices
Framework M automatically propagates standard identity headers (Auth, Tenant, Request-ID). However, you may occasionally need to pass custom application context (like an X-Affiliate-ID or a debugging flag) from the Gateway down to your macroservices.
This guide shows how to capture and propagate custom headers using the ContextMiddleware.
1. Configure the Context Middleware
The ContextMiddleware automatically captures all incoming headers and stores them in an async-safe ContextVar. You don't need to configure anything special to capture the headers; they are already available via the get_request_headers() utility.
2. Accessing Context in your Service
You can access the captured headers from anywhere in your application logic (Services, Repositories, or Adapters) without passing the request object manually.
from framework_m_standard.adapters.web.middleware.context import get_request_headers
def process_business_logic():
headers = get_request_headers()
affiliate_id = headers.get("x-affiliate-id")
if affiliate_id:
# Use the ID in your logic
...
3. Propagating to Macroservices
When you use the FederatedCompositionAdapter or any framework-native proxying mechanism, the framework automatically forwards the headers stored in the ContextVar.
Default Forwarding Behavior
By default, the framework forwards all headers except for connection-specific ones:
hostcontent-lengthconnectionaccept-encoding
This means if your browser client sends X-Affiliate-ID: 123 to the Gateway, the Gateway will automatically include X-Affiliate-ID: 123 when it calls the finance or inventory macroservices.
4. Handling Background Jobs (Temporal/Taskiq)
[!WARNING]
ContextVarsare tied to the async task of the HTTP request. They do not automatically survive the jump to a background worker.
If you need to propagate context to a background job, you must pass it explicitly in the payload:
# In your HTTP Controller
headers = get_request_headers()
tenant_id = headers.get("x-tenant-id")
# Pass it explicitly to the worker
await my_task.kickoff(tenant_id=tenant_id, data=...)
The background worker should then establish its own context or use service-to-service authentication to call downstream macroservices.