Performance

The “Performance” section isn’t about individual errors — it’s about how fast your application is: transactions (a handled request or a background operation), made up of spans (a DB query, an HTTP call to another service, template rendering, and so on), and traces — end-to-end chains of the transactions/spans belonging to a single request.

How to send the data

Transactions and spans are sent by your application’s SDK — the same official Sentry SDK you use for errors (see SDK and integrations), with tracing turned on. The key setting at init time is tracesSampleRate (the share of requests the SDK traces and sends, from 0 to 1):

Sentry.init({
  dsn: "<YOUR_DSN>",
  tracesSampleRate: 1.0, // 100% to start; usually lowered in production
});

Every language’s SDK (Go/PHP/Python, etc.) has an equivalent option — check your Sentry SDK’s docs for the exact option name and how to enable framework auto-instrumentation. As long as tracesSampleRate is zero or unset, the “Performance” section stays empty — data only shows up once the SDK actually starts sending traces.

Endpoint list

The section opens from the “Performance” entry in the left rail — URL /projects/<id>/performance (the subsection is labeled “Transactions”). Filters at the top are environment and period (1 hour / 24 hours / 7 days / 30 days). The endpoint table:

ColumnMeaning
Endpointtransaction name (click through to the endpoint page)
Throughputtransactions per minute
p50 / p75 / p95 / p99duration percentiles
Failureshare of transactions with a status other than ok
Apdexsatisfaction index, 0..1
p95 (period)a sparkline of p95 over time

Column headers are links; clicking one sorts the list by that column. The endpoint list is capped in size — if there are more real endpoints than that, a note above the table reads “showing the first N of M.”

Apdex. Below the filters the threshold T in use is shown (e.g. “Apdex T = 300ms”, configurable in project settings). A request that finishes within T counts as “satisfied,” between T and 4T as “tolerating,” slower than that as “frustrated”; Apdex = (satisfied + tolerating/2) / total. A sharp rise in p95/p99 with steady traffic is a typical sign of a degradation rather than just more load — traffic didn’t go up, so it isn’t about volume.

Endpoint detail

Clicking an endpoint’s name opens /projects/<id>/performance/<transaction>: period/environment/Apdex threshold in the header, a Web Vitals panel (if this is a page-load transaction — more on that below), a latency chart (p50/p95 over time), a throughput chart, a duration histogram, a table of the slowest traces for the period (a link to each one’s waterfall), and a list of related performance issues.

Performance issues (N+1 queries, slow DB queries, HTTP floods) are a separate, automatically detected category of findings inside transactions — not the same thing as the regressions covered later in this doc. The full list lives in the “Performance Issues” section (/projects/<id>/perf-issues), reachable from the same “Performance” subsection menu.

Trace waterfall

The “Trace” link from the slowest-traces table, or from an event’s detail in Issues, opens /traces/<trace_id>: trace id, total duration, timestamp, and below that a waterfall of the span tree (each span is a bar offset and sized by time relative to the start of the trace; spans that ended in an error are marked in red). If the trace has a linked profile (see Profiling), a link to its flame graph appears above the waterfall — a way to go from “which span was slow” to “what exactly was running inside it.”

Web Vitals

Web Vitals are page-speed metrics measured in real users’ browsers (RUM), not by a synthetic server-side check. The section opens via the “Web Vitals” tab in the “Performance” subsection menu — URL /projects/<id>/web-vitals.

MetricWhat it measures
LCP (Largest Contentful Paint)when the largest visible element finished rendering — the “page has loaded” feeling
INP (Interaction to Next Paint)responsiveness to user actions (click, tap, keypress) over the page’s whole lifetime
CLS (Cumulative Layout Shift)total layout “jumpiness” — how much elements shift unexpectedly
FCP (First Contentful Paint)when the first content rendered
TTFB (Time to First Byte)time to the first byte of the server’s response

Thresholds (Google, fixed)

The good / needs-improvement / poor rating is computed from the 75th percentile (p75) of the value over the selected period — these are Google’s official Core Web Vitals thresholds. They are not configurable per project: the same numbers apply to everyone, because this is an external, industry-standard bar, not a Gotcha-specific metric.

MetricGood (p75 ≤)Poor (p75 >)Needs improvement
LCP2500 ms4000 msin between
INP200 ms500 msin between
CLS0.100.25in between
FCP1800 ms3000 msin between
TTFB800 ms1800 msin between

The good boundary is inclusive (a p75 equal to the threshold is still “good”), a value above the poor threshold is “poor,” everything in between is “needs-improvement.”

How p75 is computed

For each page (page-load transaction) and metric, Gotcha takes the 75th percentile of the values collected over the selected filter period (1 hour / 24 hours / 7 days / 30 days) and assigns a rating from the table above. If there are no samples for a metric in the period, “—” is shown instead of a value, with no badge.

Reading the page

The table has one row per page (transaction), with p75 LCP/INP/CLS columns showing a color-coded rating badge and a sample count; sortable by clicking a column header, with the same environment and period filters as the endpoint list. On a given endpoint’s page (if it’s a page-load transaction), the same three metrics appear as a panel with a small p75-over-time chart — a quick way to see whether it recently got worse or has been stable.

The data comes from the browser SDK (@sentry/browser) with tracing enabled — without it, there’s nothing collecting Web Vitals; server-side SDKs don’t do this. Installation is covered in SDK and integrations.

Regressions

A performance regression is a statistically significant degradation in an endpoint’s p95 duration or a web vital’s p75, relative to a rolling baseline, detected automatically — without hand-tuning a threshold “by eye” for every endpoint. The list lives in the “Regressions” subsection (/projects/<id>/regressions), with “Open / Resolved / All” tabs. The table shows: target (an endpoint or a link to Web Vitals), metric, percentage increase, “baseline → peak” range, status, when it started, and duration (or “ongoing” while the regression is open).

How detection works (threshold + hysteresis)

A background evaluator periodically compares a recent window (60 minutes by default) against a baseline — the median of daily values over the last 7 days — for the project’s highest-traffic endpoints and web-vitals pages:

  • Opening only happens when two conditions both hold: a relative increase (recent > baseline × (1 + threshold)) and an absolute floor (recent > baseline + floor). The default threshold is 25%. The floor exists so that going from 20 ms to 40 ms (a nominal +100%) on numbers nobody would notice doesn’t trigger a false alarm.
  • Closing uses a looser recovery threshold — 10% by default (recent ≤ baseline × 1.10), not the same 25% used to open. This is the hysteresis: without a gap between the opening and closing thresholds, a regression would flicker open/closed right at the boundary.
  • A decision is only made when there’s enough statistics: both the recent window and the baseline need at least a minimum number of samples (100 by default), otherwise the evaluator makes no decision that tick.

Default absolute floors: 100 ms for endpoint duration, 200 ms for LCP/FCP/TTFB, 50 ms for INP, 0.05 for CLS.

All of these thresholds (opening/closing percentages, window size, minimum samples, per-metric floors, and a full on/off switch for the detector) are configurable per project — the “Regressions” card on the “Project settings” page.