Skip to main content

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:

  • host
  • content-length
  • connection
  • accept-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

ContextVars are 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.