# ADR-051: Asynchronous Context Propagation **Date**: 2026-01-11 **Status**: Accepted (Implemented) ## Context Debugging asynchronous workflows is difficult because the `request_id` generated at the API layer is lost when a task is handed off to a background queue (BullMQ). Logs from the worker appear disconnected from the user action that triggered them. ## Decision We will implement a context propagation pattern for all background jobs: 1. **Job Data Payload**: All job data interfaces MUST include a `meta` object containing `requestId`, `userId`, and `origin`. 2. **Worker Logger Initialization**: All BullMQ workers MUST initialize a child logger immediately upon processing a job, using the metadata passed in the payload. 3. **Correlation**: The worker's logger must use the _same_ `request_id` as the initiating API request. ## Implementation ```typescript // 1. Enqueueing (API Layer) await queue.add('process-flyer', { ...data, meta: { requestId: req.log.bindings().request_id, // Propagate ID userId: req.user.id, }, }); // 2. Processing (Worker Layer) const worker = new Worker('queue', async (job) => { const { requestId, userId } = job.data.meta || {}; // Create context-aware logger for this specific job execution const jobLogger = logger.child({ request_id: requestId || uuidv4(), // Use propagated ID or generate new user_id: userId, job_id: job.id, service: 'worker', }); try { await processJob(job.data, jobLogger); // Pass logger down } catch (err) { jobLogger.error({ err }, 'Job failed'); throw err; } }); ``` ## Consequences **Positive**: Complete traceability from API request -> Queue -> Worker execution. Drastically reduces time to find "what happened" to a specific user request.