{"id":17089,"library":"aws-xray-sdk-express","title":"AWS X-Ray SDK Express Middleware","description":"The `aws-xray-sdk-express` package provides middleware functions for Express.js applications to integrate with AWS X-Ray, enabling distributed tracing for incoming requests and outgoing responses. As part of the broader `aws-xray-sdk-node` monorepo, its current stable version is 3.12.0, with regular updates following the main SDK. It supports both automatic and manual tracing modes. The automatic mode, which is the default, utilizes the `cls-hooked` package for automatic context propagation across asynchronous operations, simplifying segment and subsegment management. Key differentiators include its official AWS support, seamless integration with Express.js routing, and the flexibility to choose between automatic and manual tracing paradigms to suit different application complexities and debugging needs. It requires Express 4.14.0 or greater and `aws-xray-sdk-core` as a peer dependency.","status":"active","version":"3.12.0","language":"javascript","source_language":"en","source_url":"https://github.com/aws/aws-xray-sdk-node#master","tags":["javascript","amazon","api","aws","express","xray","x-ray","x ray","typescript"],"install":[{"cmd":"npm install aws-xray-sdk-express","lang":"bash","label":"npm"},{"cmd":"yarn add aws-xray-sdk-express","lang":"bash","label":"yarn"},{"cmd":"pnpm add aws-xray-sdk-express","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Required for core X-Ray SDK functionalities like segment management and configuration.","package":"aws-xray-sdk-core","optional":false}],"imports":[{"note":"The package exports a single object containing `openSegment` and `closeSegment` middleware functions. Use a namespace import for ESM or direct `require` for CommonJS.","wrong":"import { openSegment } from 'aws-xray-sdk-express';","symbol":"xrayExpress","correct":"import * as xrayExpress from 'aws-xray-sdk-express';"},{"note":"The core SDK package exports a single object with utilities like `getSegment()`, `captureHTTPs()`, and configuration methods. Use a namespace import for ESM.","wrong":"import { getSegment } from 'aws-xray-sdk-core';","symbol":"AWSXRay","correct":"import * as AWSXRay from 'aws-xray-sdk-core';"},{"note":"For TypeScript, import the `Segment` type to correctly annotate X-Ray segment objects, especially when extending `express.Request` in manual mode or working with segment instances directly.","wrong":"import { Segment } from 'aws-xray-sdk-core';","symbol":"Segment","correct":"import type { Segment } from 'aws-xray-sdk-core';"}],"quickstart":{"code":"import express, { Request, Response, NextFunction } from 'express';\nimport * as AWSXRay from 'aws-xray-sdk-core';\nimport * as xrayExpress from 'aws-xray-sdk-express';\n\n// Configure X-Ray SDK (defaults to environment variables like AWS_REGION, AWS_XRAY_DAEMON_ADDRESS)\n// For local testing without a daemon, you might set the logger to console and disable daemon sending.\n// AWSXRay.setLogger(console);\n// AWSXRay.setDaemonAddress('127.0.0.1:2000'); // Default\n\nconst app = express();\nconst PORT = process.env.PORT || 3000;\n\n// 1. Initialize X-Ray: This middleware *must* be added before defining any routes to be traced.\n// In automatic mode, it is crucial that this is the LAST middleware added before your routes.\n// 'ExpressMicroservice' is the name that will appear for your service in X-Ray traces.\napp.use(xrayExpress.openSegment('ExpressMicroservice'));\n\n// Define your application routes\napp.get('/', (req: Request, res: Response) => {\n  // In automatic mode, getSegment() retrieves the current segment from the context.\n  const segment = AWSXRay.getSegment();\n  if (segment) {\n    segment.addAnnotation('route', 'home');\n    segment.addMetadata('user', { id: 'test-user-123', session: 'abc' });\n    console.log(`Tracing home route within segment: ${segment.id}`);\n  } else {\n    console.warn('No X-Ray segment found for home route.');\n  }\n  res.send('Hello from X-Ray Traced Express App!');\n});\n\napp.get('/data', async (req: Request, res: Response) => {\n  const segment = AWSXRay.getSegment();\n  if (segment) {\n    // Create a subsegment for an internal asynchronous operation\n    const subsegment = segment.addNewSubsegment('fetchDataOperation');\n    subsegment.addAnnotation('data_type', 'user_profile');\n    await new Promise(resolve => setTimeout(resolve, 100)); // Simulate async work\n    subsegment.close(); // Important to close subsegments\n    console.log(`Tracing data route within segment: ${segment.id}`);\n  } else {\n    console.warn('No X-Ray segment found for data route.');\n  }\n  res.json({ message: 'Data fetched successfully' });\n});\n\n// 2. Close X-Ray Segment: This middleware *must* be added after all routes to be traced.\n// In automatic mode, it must be the FIRST middleware added AFTER your routes (or before error handlers).\napp.use(xrayExpress.closeSegment());\n\n// Optional: Error handling middleware for tracing errors\napp.use((err: Error, req: Request, res: Response, next: NextFunction) => {\n  if (AWSXRay.isCurrentSegmentAvailable()) {\n      AWSXRay.getSegment()?.addError(err);\n  }\n  console.error('An error occurred:', err.message);\n  res.status(500).send('Something broke!');\n});\n\napp.listen(PORT, () => {\n  console.log(`Server listening on port ${PORT}`);\n  console.log('Ensure X-Ray daemon is running locally or AWS credentials/environment variables are configured for tracing.');\n});\n","lang":"typescript","description":"This quickstart demonstrates setting up an Express application with AWS X-Ray tracing in automatic mode, including middleware for segment opening/closing, accessing the current segment, adding annotations and metadata, and handling subsegments for internal operations. It also includes basic error handling."},"warnings":[{"fix":"Place `app.use(xrayExpress.openSegment('name'))` immediately before your `app.get`, `app.post`, etc., calls, and `app.use(xrayExpress.closeSegment())` immediately after all route definitions and before any final error handlers.","message":"The order of `openSegment` and `closeSegment` middleware is critical in automatic mode. `openSegment` MUST be the last middleware before your routes, and `closeSegment` MUST be the first middleware after your routes (or before error handlers) to ensure correct context propagation and segment closure.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"Ensure critical async operations are wrapped by X-Ray SDK functions (e.g., `AWSXRay.captureAsyncFunc`) if context is manually being managed, or simplify async flows to allow `cls-hooked` to maintain context. Avoid `new Promise` without `AWSXRay.captureAsyncFunc` for non-traced async work.","message":"Automatic tracing mode relies on `cls-hooked` for asynchronous context propagation. While generally robust, complex asynchronous patterns or mixing `cls-hooked` with other context management libraries can lead to context loss and missing trace data.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"If using automatic mode (default), always retrieve the current segment using `AWSXRay.getSegment()`. If explicitly configured for manual mode, access the base segment via `req.segment`.","message":"Distinguish between automatic mode segment access (`AWSXRay.getSegment()`) and manual mode segment access (`req.segment`). Using the wrong method for your configured mode will result in `undefined` segments.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"Always refer to the official CHANGELOG for `aws-xray-sdk-node` when performing major or minor version upgrades to understand potential breaking changes or deprecated features affecting the Express middleware.","message":"The `aws-xray-sdk-node` monorepo, which includes `aws-xray-sdk-express`, deprecated version `3.7.0`. While this specific package is at 3.12.0, be aware of deprecations and breaking changes in the core SDK when upgrading entire `aws-xray-sdk-node` packages.","severity":"breaking","affected_versions":"3.7.0 (aws-xray-sdk-node)"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Ensure `import * as AWSXRay from 'aws-xray-sdk-core';` (ESM) or `const AWSXRay = require('aws-xray-sdk-core');` (CommonJS) is present at the top of your file.","cause":"The `aws-xray-sdk-core` module was not imported or required correctly, or `AWSXRay` was used before its declaration.","error":"ReferenceError: AWSXRay is not defined"},{"fix":"Check if `AWSXRay.getSegment()` returns a valid segment before attempting to call methods on it, e.g., `const segment = AWSXRay.getSegment(); if (segment) { segment.addAnnotation(...); }`. Verify that `openSegment` middleware is correctly placed and X-Ray sampling rules allow tracing for the incoming request.","cause":"The `segment` variable is `null` or `undefined`, indicating no X-Ray segment is currently available in the context or the request was not sampled.","error":"TypeError: segment.addAnnotation is not a function"},{"fix":"Ensure `xrayExpress.closeSegment()` is the first middleware after all your routes, typically before any generic error-handling middleware that might send responses.","cause":"The `xrayExpress.closeSegment()` middleware is placed after a response has already been sent to the client, or an error handler sends a response and then `closeSegment` attempts to modify headers.","error":"Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client"},{"fix":"Verify that `xrayExpress.openSegment` is correctly applied to all desired routes and that the X-Ray daemon is running and reachable if you expect traces to be sent. Ensure `AWS_XRAY_CONTEXT_MISSING` is set to 'LOG_ERROR' or 'IGNORE' if you want to control how missing contexts are handled (default is LOG_ERROR).","cause":"This warning (often from logs) indicates that an operation attempting to access the current X-Ray segment (e.g., `AWSXRay.getSegment()`) was executed outside of an active trace segment context, or the request was not sampled.","error":"No X-Ray segment found in context."}],"ecosystem":"npm","meta_description":null}