How to Use Sentry Performance Tracing to Find Slow Requests

October 22, 2026

Sentry performance tracing records a transaction per request with nested spans for each operation, so you can see that a 2.4-second API call spent 1.9 seconds waiting on Postgres. Enabling it takes one config flag and a sampling decision; reading it well takes knowing which spans to add yourself.

The quota maths comes first. Tracing bills per span, and an uninstrumented request can quietly emit dozens.

What Is a Span and What Does Tracing Actually Record?

A transaction is the whole request. A span is a unit of work inside it — a database query, an HTTP call, a function you wrapped. Spans nest, forming a waterfall.

Automatic instrumentation covers HTTP servers, common database drivers, and fetch clients. Everything in your business logic needs Sentry.startSpan() wrapped around it, which is the part most teams skip and then wonder why the waterfall stops at the controller.

How Do I Choose a tracesSampleRate Without Blowing the Quota?

Estimate before enabling. Take monthly requests, multiply by average spans per request, multiply by the sample rate.

Traffic Average spans Sample rate Monthly spans
1M requests 20 0.1 2M
1M requests 20 0.01 200k
10M requests 10 0.05 5M

The Team plan includes a span allowance in the low millions; higher volumes are billed on top. Start at 0.05 and raise it only if you cannot find your slow path.

A useful trick: sample high for slow requests and low for fast ones. Sentry supports this through tracesSampler, where you return a rate based on the transaction context.

How Do I Add Custom Spans That Answer Questions?

Wrap the operations you suspect, not everything.

  • Sentry.startSpan({ name: 'invoice.generate' }, () => ...) around a suspected hot path.
  • op: 'db.query' on manual queries so they group with automatic ones.
  • op: 'http.client' on outbound calls to third parties.

Add attributes to spans rather than creating new span names for each variant: span.setAttribute('invoice.items', count) keeps the waterfall readable while preserving the detail. Span name cardinality is what makes trace views unusable on large projects.

How Do I Read the Waterfall to Find the Real Problem?

Open a trace and look for the widest bar, not the deepest one. Width is time; depth is call hierarchy. People reflexively scroll to the bottom leaf, but the 1.8-second gap between two spans usually means something unaccounted for — a synchronous block, a DNS lookup, or a wait on a lock.

Sort transactions by p95 duration rather than average. A 40 ms average with a 3-second p95 is a page that times out for one user in twenty, and averages hide it entirely.

What Are the Common Instrumentation Mistakes?

Three, consistently:

  1. Sampling at 1.0 in staging and copying the config to production.
  2. Leaving the front-end browserTracingIntegration with default tracePropagationTargets, which drops the trace header on cross-origin API calls and splits your waterfall into two unlinked traces.
  3. Wrapping spans around code that already has automatic instrumentation, doubling the span count for the same work.

When Is Tracing Not Worth the Spend?

If your p95 is under 200 ms, there is no user-visible problem to chase. Optimizing a 120 ms endpoint to 90 ms is engineering theatre.

Also skip it if your bottleneck is already known — a missing database index shows up in slow query logs for free. Tracing earns its cost on distributed systems where the slow step is not obvious from any single service’s logs.

Quick Summary

  • A transaction is the request; spans are nested operations inside it.
  • Estimate spans as requests × spans per request × sample rate before enabling.
  • Start at 0.05 sample rate and use tracesSampler to favour slow requests.
  • Read the widest bar, not the deepest leaf, and sort by p95 not average.
  • Tracing only pays off when the bottleneck is genuinely unknown.
Tags: