Skip to main content
Once APM is enabled, the Performance section of a bucket answers two questions: is anything slow, and where does the time go (Overview), and which query or connection is responsible (Operations). Everything is scoped to the bucket, environment and time period selected in the dashboard.

Overview

The overview reads per-request rollups rather than individual spans, so it stays fast at any traffic volume. Summary — requests, error rate, median / p95 / p99 latency, total time consumed, the share of time spent waiting on dependencies, and how many operations ran. Time Breakdown — where request time went over the period, split into database, cache, outbound HTTP, queue/RPC and application time. Application time is the residual: request duration minus the instrumented families, floored at zero. Because dependency work can overlap, a heavily parallel endpoint can show little or no application time. Endpoints By Time Consumed — endpoints ranked by total time rather than average latency, with requests, errors, average, p95, p99 and the same dependency split per endpoint. A 30 ms endpoint called a million times costs more than a 4 s endpoint called twice, and this ranking is what surfaces it. Regressions — endpoints whose p95 or error rate moved against a baseline, ranked by the time the change costs. Choose the baseline: the previous window (the period immediately before the one selected) or the same window a week ago, which is the better comparison for traffic with a weekly shape. Endpoints below a minimum request count are ignored so that noise from rarely called routes does not crowd out real movement.
Regression detection is read-time and on-demand. Alert delivery (Slack, webhooks) is not part of it — use events and workflows for notification today.

Streams and long-lived connections

A streaming response stays open for as long as its client listens, so its duration is how long the connection was open, not how long the server took to respond. Responses sent as text/event-stream (Server-Sent Events, such as MCP’s GET /mcp/sse) are marked as streams automatically, and you can mark other long-held connections, such as long polling, with the Long-lived connection option on an endpoint rule. Streams are counted everywhere requests are counted — request totals, throughput and error rates — but are left out of response-time metrics: average, median, p95 and p99 latency, slow operations and response-time charts. A single stream held open for five minutes would otherwise outweigh thousands of ordinary requests. The SDKs also record each request’s time to first byte: how long the server took to start responding. For a stream, that is the number that reflects how quickly it was served, and it is shown alongside the open time in the request list and request detail.

Operations

The Operations tab aggregates spans across requests. Choose what to group by: The two endpoint groupings answer opposite questions and are never mixed. Inbound Endpoint is your own endpoint — the request that made the calls. Outbound Endpoint is the endpoint on the service you called, normalized the same way your own paths are and qualified by the host that served it, so POST api.stripe.com /v1/charges/{id} never collapses into the same row as the identical path on another vendor. Selecting either outbound grouping scopes the report to outbound HTTP, since a database or cache span has no destination endpoint. Outbound endpoint rules scoped to a host apply here, so you control how a vendor’s paths are grouped.

Upstream failures

Outbound groupings carry an extra Upstream Failures column and sort: the share of that group’s calls that returned 5xx or never got a response at all, with the 5xx, no-response and 4xx counts underneath. 4xx is deliberately excluded from the rate — a 401 or a 404 is normally your request being wrong rather than the dependency breaking, and folding it in hides a real outage inside a steady stream of 404s. A call that timed out, was refused or failed DNS has no status at all; it is reported as no response (status 0), which is a different failure from a 5xx and is counted separately. Sort an outbound grouping by Upstream Failures to see which dependency is failing right now. Opening a row flags an elevated rate and charts upstream failures over time next to runs, so a dependency that just started failing shows up as a line lifting off zero while your own traffic stays flat. On the API, /spans/reports and /spans/timeseries accept outStatusClass (2xx, 3xx, 4xx, 5xx, none) and outStatusCode for an exact status, and every row and bucket returns outCalls, outServerErrorCount, outNoResponseCount and outClientErrorCount. Each row shows runs, runs per request, average, p95, p99, total time and errors, and can be sorted by any of them. Total time is usually the right sort — it is what actually costs your users. Rows that run many times per request are badged N+1. That is the classic symptom of a query issued inside a loop: individually fast, collectively ruinous. Because code location capture is on by default, each row carries the file, line and function that issued the operation, and Code Location is a grouping of its own — ranking your own source lines by the time they spend waiting on dependencies. Opening a row also shows a representative stack trace: the callers that led to the operation, innermost first. Code locations only exist for spans recorded while capture was on, so a group from a bucket with it switched off (or from before it existed) reads as (no code location captured). Selecting a row opens the operation, with:
  • full statistics for the group (runs, distinct requests, runs per request, quantiles, total time, type, system, host, database, inbound endpoint, outbound endpoint, code location, last seen);
  • a trend chart of that operation over time — runs, errors and latency quantiles — so you can see whether it has always been slow or started recently;
  • the requests it ran in, so you can jump straight from a slow query to a real request that executed it and inspect the whole waterfall.

Inside a request

Open any request in Traffic to see the same data from the other direction. Time breakdown — a bar above the waterfall showing how this specific request’s duration split across database, cache, outbound, queue/RPC and application time. Waterfall — every span on a timeline, positioned by when it started relative to the request and sized by duration, with failed operations marked. Selecting a span opens its details: duration, start offset, end offset, share of the request, and all metadata the instrumentation provided — operation, method, status, system, database, table or collection, host, path, route, URL, command, key, rows, user, connection pool, transport, span kind, instrumentation scope, errors, and the code location when captured. Statements and parameters render as code blocks. Anything an instrumentation attached that ApiTraffic does not have a label for is still shown under its own key — the pane never hides data it received. Distributed Trace — every request that shares this request’s trace id, in time order, with status, duration and span count. This is how a call that crosses several of your services reads as a single timeline; see how traces are resolved.

Querying it yourself

Everything above is available over the API:

APM API

Time breakdown, endpoint ranking, regressions and trace lookup

Spans API

Operation reports, per-operation trends and drill-back to requests