X-Ray for Lambda and API Gateway
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Understanding Distributed Tracing: AWS X-Ray for Lambda and API Gateway
Introduction: Why Distributed Tracing Matters
In modern cloud architecture, we rarely build monolithic applications that live on a single server. Instead, we rely on distributed systems, microservices, and serverless components like AWS Lambda and Amazon API Gateway. While this modular approach allows for greater scalability and developer velocity, it introduces a significant challenge: visibility. When a user experiences a slow response or a failed request, pinpointing exactly where the issue occurred across a dozen different services can feel like finding a needle in a haystack.
Distributed tracing is the practice of tracking a request as it travels through various components of your application. It provides a "map" of the entire journey, showing you how much time was spent in the API Gateway, how long the Lambda function took to execute, and how long downstream services—like a DynamoDB table or an external third-party API—took to respond. Without distributed tracing, you are left to stitch together logs from different services based on timestamps, which is error-prone and inefficient.
AWS X-Ray is the service designed specifically for this purpose. It collects data about requests that your application serves and provides tools to view, filter, and gain insights into that data to identify issues and opportunities for optimization. In this lesson, we will explore how to integrate X-Ray with AWS Lambda and API Gateway, how to interpret the data, and how to use these tools to build more reliable and performant serverless applications.
The Core Concepts of AWS X-Ray
Before diving into the configuration, it is important to understand the fundamental building blocks of X-Ray. These terms appear constantly in the AWS console and documentation, and knowing them will help you navigate the service more effectively.
Traces, Segments, and Subsegments
At the heart of X-Ray is the Trace. A trace represents the entire path of a single request from the moment it enters your system (e.g., at the API Gateway) to the moment it finishes.
- Segments: A segment represents the work done by a single service or component in the trace. For example, your Lambda function constitutes one segment.
- Subsegments: These provide a more granular view of the work performed within a segment. If your Lambda function calls a database, the database call is a subsegment of the Lambda segment.
- Annotations and Metadata: These are key-value pairs that you can attach to segments or subsegments. Annotations are indexed by X-Ray, allowing you to filter traces based on these values (e.g.,
user_id,order_status), while metadata is for storing larger amounts of information that you don't need to search by.
Callout: Tracing vs. Logging While logs are excellent for recording the internal state of an application at a specific moment in time, they are often disconnected. Tracing is about the lifecycle of a request. You use logs to understand what happened, and you use traces to understand where the latency is occurring and how the different parts of your system interacted.
Setting Up X-Ray for API Gateway
API Gateway serves as the entry point for most serverless applications. Enabling X-Ray here is the first step in creating a complete trace. When enabled, API Gateway automatically generates a "trace ID" for every incoming request and passes it to the downstream services, including your Lambda functions.
Steps to Enable Tracing in API Gateway
- Navigate to the API Gateway console in your AWS account.
- Select the API you wish to instrument.
- Go to the Stages section in the left-hand navigation pane.
- Select the stage you want to enable (e.g.,
prodordev). - In the Logs/Tracing tab, check the box labeled Enable X-Ray Tracing.
- Save your changes and redeploy the API.
Once enabled, API Gateway will start sending trace data to X-Ray. If your API is invoked, you will see a service map in the X-Ray console showing the API Gateway as the starting node of your request path.
Integrating X-Ray with AWS Lambda
Enabling X-Ray in API Gateway is only half the battle. To see what happens inside your Lambda code, you must also enable tracing for the function itself.
Enabling Tracing on a Lambda Function
You can enable tracing via the AWS Management Console or Infrastructure-as-Code (IaC) tools like AWS SAM or Terraform.
Using the Console:
- Open the Lambda function in the AWS console.
- Navigate to the Configuration tab.
- Select Monitoring and operations tools.
- Click Edit and toggle Active tracing to "On".
Using AWS SAM (Template.yaml):
Resources:
MyFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs18.x
Tracing: Active # This enables X-Ray for the function
Warning: Cost Considerations AWS X-Ray charges based on the number of traces recorded. While the first 100,000 traces per month are free, high-traffic applications can incur significant costs if every single request is traced. Consider using sampling rules to trace only a percentage of your traffic, which is often sufficient for identifying performance trends.
Advanced Instrumentation: Adding Custom Subsegments
While the automatic instrumentation provided by AWS SDKs is powerful, you often need more detail. For example, if your Lambda function performs three different database operations, the automatic trace will show the Lambda as a single block. By adding custom subsegments, you can see exactly which of those three operations is the slowest.
Example: Node.js with AWS X-Ray SDK
To add custom subsegments, you need to use the aws-xray-sdk library.
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
exports.handler = async (event) => {
// Creating a custom subsegment
return await AWSXRay.captureAsyncFunc('DatabaseOperation', async (subsegment) => {
try {
const db = new AWS.DynamoDB.DocumentClient();
const data = await db.get({ TableName: 'MyTable', Key: { id: '123' } }).promise();
// Adding an annotation for filtering later
subsegment.addAnnotation('UserID', '123');
return data;
} catch (err) {
subsegment.addError(err);
throw err;
} finally {
subsegment.close();
}
});
};
Breaking down the code:
AWSXRay.captureAWS: This automatically wraps all AWS SDK calls, ensuring that calls to S3, DynamoDB, or SQS are automatically traced.AWSXRay.captureAsyncFunc: This is the method used to manually define a subsegment. It handles the lifecycle of the subsegment automatically.subsegment.addAnnotation: By adding theUserID, we can now go into the X-Ray console and search for all traces involving a specific user, which is invaluable for debugging user-specific issues.
Analyzing Traces in the X-Ray Console
Once you have your traces flowing, the X-Ray console becomes your primary workspace. The most important feature here is the Service Map. This visual representation shows the nodes (services) and the edges (the flow of requests) between them.
Key Metrics in the Service Map
- Color coding: Nodes are colored based on their health. Green indicates a successful request rate, while red indicates errors (4xx or 5xx).
- Response time distributions: By clicking on an edge, you can see a histogram of response times. This helps you identify if your system is experiencing "tail latency," where most requests are fast, but a small percentage are extremely slow.
- Trace List: Below the map, you will find a list of individual trace IDs. You can click on any trace to open the "Trace Detail" view.
The Trace Detail View
This view shows a waterfall diagram of the request. You will see a timeline that starts at the API Gateway, moves into the Lambda, and then shows the various subsegments within the Lambda. This is where you can identify the "bottleneck"—the specific point in the timeline where the bars are longest.
Callout: Understanding Latency When looking at a trace, always pay attention to the gap between subsegments. If there is a large gap between the end of one database call and the start of another, that time is spent in your application logic (e.g., data processing or waiting for a variable to be assigned). If the bar itself is long, the time is spent waiting on the external resource (e.g., the database engine).
Best Practices for Distributed Tracing
- Use Sampling Rules: Do not trace 100% of your requests unless you are in a specific debugging session. Configure sampling rules to trace, for example, 5% of requests, or a higher percentage for specific API endpoints that are known to be problematic.
- Keep Annotations Lean: Annotations are indexed, which makes them powerful for searching, but they have size limits. Use them for high-cardinality data like
UserID,OrderID, orRegionID. Do not put large JSON blobs into annotations; use metadata for that. - Ensure Proper Permissions: Your Lambda function needs the
xray:PutTraceSegmentsandxray:PutTelemetryRecordsIAM permissions to send data to X-Ray. If these are missing, your code will run, but you will see no traces in the console. - Propagate Trace IDs: If your system calls other internal systems that you manage, ensure that you pass the
X-Amzn-Trace-Idheader along with your requests. If you don't pass this header, the downstream service will start a "new" trace, and you will lose the connection between the two services. - Use X-Ray with Infrastructure-as-Code: Always define your tracing settings in your SAM template or Terraform files. This ensures that tracing is enabled consistently across all environments (dev, staging, prod) and prevents "configuration drift."
Common Pitfalls and How to Avoid Them
1. The "Disconnected Trace" Problem
Many developers find that their traces stop at the Lambda function and do not continue to downstream services. This usually happens because they are using an HTTP client that is not "X-Ray aware."
- Solution: Use the
aws-xray-sdkto patch your HTTP client. For Node.js, you can usecaptureHTTPsto wrap the standardhttpsmodule. This ensures that any outgoing HTTP request automatically carries the trace ID.
2. Over-instrumentation
Adding too many subsegments can make your trace waterfall diagram difficult to read and can actually add latency to your function because of the overhead of reporting to X-Ray.
- Solution: Focus on instrumenting the "edges" of your system—network calls, database operations, and calls to other AWS services. Don't wrap every single function call in your code in a subsegment.
3. Ignoring the "Error" State
Sometimes a request finishes successfully, but the business logic failed (e.g., a 404 error). X-Ray might color this as "green" because the HTTP status code was 200, or it might mark it as a fault.
- Solution: Use the
addAnnotationmethod to mark failed business logic as an error, even if the HTTP status is technically successful. This allows you to filter for "logical errors" in your traces.
Comparison: Tracing vs. Traditional Monitoring
| Feature | Traditional Metrics (CloudWatch) | Distributed Tracing (X-Ray) |
|---|---|---|
| Primary Focus | Aggregated health (CPU, Memory, Error count) | Individual request lifecycles |
| Use Case | Identifying that a service is slow | Identifying why a service is slow |
| Data Format | Time-series graphs | Waterfall diagrams and service maps |
| Granularity | System-level or service-level | Code-level and request-level |
| Best for | Proactive alerting and capacity planning | Troubleshooting and performance tuning |
Step-by-Step: Troubleshooting a Slow Lambda
If your users are complaining about slow API responses, follow these steps to use X-Ray to find the culprit:
- Filter by Latency: Go to the X-Ray console and use the filter bar to search for traces where
duration > 2000(for a 2-second threshold). - Sort by Time: Look at the list of traces that match your filter. Select one that represents the typical "slow" request.
- Analyze the Waterfall: Open the trace and look at the timeline.
- If the "API Gateway" segment is long, the latency is in the gateway itself (likely due to authorizers or request validation).
- If the "Lambda" segment is long, look inside the Lambda subsegments.
- If a specific database call subsegment is long, check the database performance metrics (e.g., DynamoDB throttles or long-running queries).
- Correlate with Logs: Use the Trace ID to jump directly to the CloudWatch logs for that specific request. Since you have the trace ID, you can filter your logs to see exactly what the function was doing during those slow milliseconds.
- Remediate: Based on the finding, either optimize the database query, increase Lambda memory (which gives you more CPU), or implement caching.
Frequently Asked Questions (FAQ)
Q: Does X-Ray slow down my Lambda functions? A: There is a negligible performance overhead when using the X-Ray SDK. The SDK runs asynchronously, meaning it sends the trace data to the X-Ray daemon after the function has already responded to the user. You should not see a significant impact on your response times.
Q: Can I use X-Ray for services running on EC2 or ECS? A: Yes. While this lesson focused on Lambda, X-Ray supports almost any compute environment on AWS. You simply need to install the X-Ray daemon on your EC2 instance or as a sidecar container in your ECS task.
Q: How long is X-Ray data stored? A: X-Ray retains trace data for 30 days. After that, the data is automatically deleted. If you need long-term storage for compliance or auditing, you can configure X-Ray to export data to an S3 bucket.
Q: What if my Lambda function calls a non-AWS API?
A: You can still trace this! As long as you use the captureHTTPs or equivalent instrumentation in your language of choice, the X-Ray SDK will record the outgoing HTTP call as a subsegment, showing you exactly how long the third-party service took to respond.
Key Takeaways
- Visibility is Paramount: In distributed systems, you cannot debug what you cannot see. X-Ray provides the necessary visibility into the path of a request across services.
- Start with the Basics: Enable X-Ray on API Gateway and Lambda via your IaC templates as a baseline. This requires no code changes and provides immediate value.
- Instrumentation is Key: Use custom subsegments and annotations to turn generic traces into meaningful data that aligns with your business logic (e.g., tracking by
UserIDorOrderID). - Sampling is Essential: Manage your costs and performance by implementing sampling rules. You don't need to trace everything to gain actionable insights.
- Bridge the Gap: Always ensure that your HTTP clients are instrumented so that trace IDs are propagated downstream. A broken trace chain is the most common cause of "missing" information.
- Use Traces to Inform Optimization: Don't guess which part of your code is slow. Use the waterfall diagram to identify the exact subsegment responsible for latency and focus your optimization efforts there.
- Integrate with Logs: Always treat X-Ray and CloudWatch Logs as a pair. Use X-Ray to identify the problem area and use CloudWatch Logs to examine the specific error messages or code state.
By mastering these techniques, you move from "reactive debugging"—where you guess what went wrong—to "observability-driven development," where you have the data needed to make informed decisions about your system's performance and reliability. Start small, enable tracing in your next project, and watch how much easier it becomes to keep your services running smoothly.
Continue the course
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons