Tracing & Performance

APM vs Distributed Tracing: How They Fit Together

APM aggregates; tracing follows one request. Learn how transactions, spans, and traces relate, and why you need both to find a slow path across services.

Most teams ask the wrong question when they compare APM and distributed tracing — they ask "which one do I need?" when they should ask "at what altitude do I need to see?" These are not competing tools. They're the same observability data viewed at different scales. APM tracing gives you the aggregate: "Your checkout endpoint's p95 is 1.2 seconds across 40,000 requests this hour." Distributed tracing gives you the single request: "THIS checkout took 4 seconds, and 3.6 seconds of it was stuck waiting for the inventory service's database query." APM tells you something is slow. Tracing tells you where the time went. You need both because the aggregate points you at the problem, and the trace lets you fix it.

The confusion exists because they're built on the same foundation. Every request in your system becomes a transaction, which is nothing more than the root span of a trace. When you measure that transaction's duration and name it by route — GET /checkout — you're creating the raw material for APM aggregation. Percentiles are computed across hundreds or thousands of those transactions; a trace is just one individual transaction opened and examined under a microscope.

What APM answers versus what distributed tracing answers

These two tools measure the same system but answer fundamentally different questions.

QuestionAPM or Tracing?
What's my slowest endpoint?APM
Why is THIS specific request slow?Tracing
What's my p95 latency?APM
Where in the stack did those 500ms get consumed?Tracing
Are errors correlated with slowness?Both
How many requests per second hit checkout?APM
Which service is causing the timeout in this trace?Tracing
Which deploy introduced slowness?APM (via releases)
What was the exact sequence of operations that led to the error?Tracing

APM answers questions about your entire system's health. What is APM explains it fully, but in brief: it captures transaction metrics — throughput, percentiles, error rates, response times — and groups them by endpoint or operation name. You get dashboards showing "API checkout is averaging 200ms but p95 is 2.1 seconds, with a 0.3% error rate, over the last hour." This tells you something is wrong, and which endpoint to investigate.

Distributed tracing answers questions about a specific execution path. What is distributed tracing walks you through the mechanics, but the essence is: a trace ID follows a single request from entry to exit, collecting spans for every database query, API call, cache lookup, and operation. You open a trace and see a waterfall showing that out of 4 seconds, 0.5 seconds went to validating the user, 3.2 seconds went to the inventory service (the bottleneck), and 0.3 seconds went to payment processing. This tells you exactly where the time went, so you can fix it.

The payoff is in the workflow: click the p95 latency bar in your APM dashboard, drill into the slowest transactions, open a representative trace, examine the span waterfall, and see which service consumed the time. That drill-down — from aggregate to outlier to individual trace to specific span — is how modern teams debug production.

The drill-down workflow: aggregate to the fix

Here's how APM and tracing work together in practice.

You're on call. Your team's error-tracking dashboard (where you see errors and performance metrics thanks to LightTrace) shows that your POST /checkout endpoint has started timing out. The p95 latency is 8 seconds when it should be 1 second. No errors are being thrown — the requests are succeeding, just slowly.

Step 1: APM aggregate. You look at the performance metrics for that endpoint. Throughput is normal (50 req/s), error rate is 0%, but the p95 jumped. You see the issue is recent — the trend shows it started 20 minutes ago.

Step 2: Find an outlier. You switch to the "slow transactions" view and LightTrace shows you individual slow checkouts. You pick one that took 7.8 seconds.

Step 3: Open the trace. You click that transaction and LightTrace opens its full distributed trace. The trace ID propagated through all your services, so you see one unified waterfall. The root span is POST /checkout. Below it are child spans: database queries, an HTTP call to your inventory service, a call to Stripe.

Step 4: Read the waterfall. The inventory-service call took 7.1 out of 7.8 seconds. That's your problem. You click into that span and see it made two database queries: one took 6.9 seconds.

Step 5: Fix it. You jump to your database and run that query directly. It's doing a full table scan when it should use an index. You add the index, deploy, and the p95 drops back to 1.2 seconds.

Without APM, you wouldn't have known POST /checkout was the culprit among 50 endpoints. Without tracing, you'd see "inventory service is slow" but not which query was slow. Together, they compressed a 2-hour debugging session into 10 minutes.

LightTrace combines both: your Sentry SDK captures transaction metrics automatically, and every transaction is also a traceable request. No separate tool. No separate DSN. One setup, both views.

Transaction naming: the cardinality trap

The bridge between APM and tracing is the transaction name. A transaction is exactly what gets aggregated in your APM dashboard. Name it well, and your metrics are useful. Name it poorly, and they're useless noise.

Here's the trap: imagine you're instrumenting a user endpoint that takes a user ID as a parameter. You might name the transaction:

GET /users/12345

That works — for one request. But you have 100,000 users. So now your APM dashboard shows 100,000 different "transaction names," each with a sample size of one. You can't compute percentiles. You can't spot trends. Your p95 becomes meaningless because there is no p95 — there's just one request per endpoint, buried in noise.

The fix is to parameterize:

GET /users/:id

Now all user fetches roll up into one bucket. You can see that GET /users/:id has p95 of 45ms and p99 of 200ms. When it spikes to 1 second, you know something's wrong.

High-cardinality observability is a deeper dive into this, but the principle is simple: transaction names should be the route or operation, not the data. Templates, not instances. This is one of the most common mistakes teams make when they first set up APM, and it tanks their ability to see patterns. Traces don't care about cardinality — one trace is one request, high-cardinality or not — but APM aggregates require low-cardinality names to be useful.

Sampling: when your metrics and traces disagree

Here's a practical tension you'll run into: APM metrics want completeness, but distributed traces are usually sampled.

By default, when you set up an Sentry SDK with LightTrace, transactions are captured at a sample rate — maybe 10% or 100%, depending on your volume. If you sample 10% of transactions, you're sending 90% fewer traces to LightTrace, which saves bandwidth and storage. But your APM metrics (throughput, p95, error rate) are computed from all transactions, sampled or not. The SDK counts them locally.

This means your APM dashboard can show "p95 is 1.2 seconds" based on 100% of traffic, while the traces you store are only a 10% sample. Most of the time, this is fine — the sample is representative. But occasionally you'll see a slow transaction in the dashboard that isn't stored as a trace, because it happened to be in the 90% you didn't sample.

The more sophisticated answer is tail sampling: instead of sampling randomly, you sample based on latency or error status. Sample 100% of slow or failing requests, and only 1% of fast successes. This way, your stored traces emphasize the problems you actually need to investigate. Head and tail sampling in tracing explains the tradeoffs more deeply, but the point here is simple: be aware that your metrics and your traces may not tell exactly the same story, and that's by design.

Don't set your sample rate to 0.01% thinking you'll save money — you'll lose visibility into actual problems. A good rule of thumb: sample high enough that you capture at least one trace per transaction type per hour, more if you have high volume.

Where errors fit into the picture

An error that occurs inside a transaction creates a span that's marked as failed. When that error is reported to LightTrace, it carries the trace ID and span ID, so you're not just seeing "TypeError: cannot read property X of undefined" in isolation. You see it in context.

The full picture: your POST /checkout transaction took 4 seconds, it made a database call (12ms), then an API call to the payment service (3.8 seconds, and the payment service hit a timeout), then the code tried to log the result but the response was malformed, throwing an error. Without the trace, you'd see only the error. With it, you see the sequence: this error occurred here in the call chain after this specific latency.

For teams building reliability, this is gold. Most outages aren't "code is broken." They're "service A timed out, so service B retried, so service C overloaded, so the entire flow failed." Distributed traces make that cascade visible. APM makes you aware it happened. Together, they're how you prevent the next one.

LightTrace's cross-project tracing stitches errors and traces together across multiple services, so even if your inventory and payment services report to different projects, one trace shows the full path.

Conclusion

APM and distributed tracing aren't competing technologies. They're two views of the same data. APM is the aerial view — you see all your endpoints, their health trends, where problems cluster. Distributed tracing is the ground view — you pick one transaction and see every operation, every millisecond, every service hop. Start with APM to detect that something is wrong. Use tracing to find out where. Deploy a fix knowing exactly what broke.

If you're not yet monitoring your performance, start with both. Most teams that instrument error tracking also have the foundation for tracing already in place — the same Sentry SDK, the same trace ID propagation. The difference is just a sample rate and a dashboard. Point it at LightTrace, flip on tracing, and you'll have both views live in minutes.

Start tracking errors in minutes

Monitor both the aggregate health and individual request paths — point your Sentry SDK at LightTrace to capture transactions and traces together.

Fix your next production error faster

Point any Sentry SDK at LightTrace — free up to 5,000 events/month.