Performance
Each page's response time over time, the before/after deploy, and the “normal” band.
Updated on 25 September 2026
On this page
- What PostShip measures
- The paces
- The windows
- The curve
- Before / after the last deploy
- The rest of the page
- What triggers an alert
- Limits and plans
- Troubleshooting
- Why does the page say “No measurement yet”?
- Why is the before/after comparison empty?
- Latency threshold
- What PostShip checks
- Set it up
- What triggers an alert
- Limits and plans
- Troubleshooting
- Latency anomalies
- The baseline
- The formula
- What triggers an alert
- Where to see it
- Set it up
- Limits and plans
- Troubleshooting
Every check of a URL records its response time, the TTFB: the time the page takes to start responding, measured from PostShip's server. The Performance page answers the only question you ask in front of these measurements, “is my site slowing down, and since when”: the median, the 95th percentile, the curve, and the comparison before/after the last deploy. What your visitors measure, for their part, is on Real vitals.
What PostShip measures
Only URLs of kind HTTP, form and journey carry a response time that means “the page”: a certificate or a sitemap have one too, but nobody waits for them behind a browser. For each URL, over the chosen window:
| Column | Meaning |
|---|---|
| p50 | The median: the ordinary experience |
| p95 | The 95th percentile: the one visitor in 20 who waits the most |
| max | The worst run |
| n | The number of measurements |
The summary at the top of the page names the slowest page and what it's worth: “The slowest page is /checkout: 640 ms median, 1,200 ms for the unluckiest visitor in 20.”
The paces
The thresholds are those of perception, not of infrastructure: under 200 ms you see nothing, under 500 ms you don't complain, under one second you wait, beyond that you leave.
| Pace | Median |
|---|---|
| Fast | under 200 ms |
| Fair | 200 to 499 ms |
| Slow | 500 to 999 ms |
| Very slow | 1,000 ms and more |
The windows
24 h (one point every 15 minutes), 7 days (one point every 2 hours, the default window), 30 days (one point every 6 hours), 90 days (one point every 18 hours). All 4 windows come with the page: switching between them is immediate. A window longer than the plan's retention is closed, with the reason: “Your plan keeps 7 days of history. 30 days requires keeping more.” A link to a closed window falls back to the largest available rather than showing an error.
Gaps are kept: a curve that connected 2 measured points would hide an interruption of monitoring.
The curve
A chart shared by all URLs, at the same scale, because the comparison between pages is the chart's point. The 5 slowest are lit at start; click a URL to light it or turn it off. 3 more things are drawn:
- The production deploys of the window: a thin vertical line, with the SHA. A slowdown is almost always a ship, and the line is there to see it.
- The “normal” band: when a single curve is lit, the greyed area is the median ± 2 robust deviations of that page at that hour of the week, over 14 days, that is 95% of the usual runs. Narrower than the alert threshold, on purpose: the chart shows the habit, the alert only rings well beyond. Without a reference for a slot, a blank. See Latency anomalies.
- The anomaly dots: a red dot at the exact instant of a run recorded “abnormally slow”, with its sentence: “3× slower than usual at this hour (1,850 ms against 600 ms normally)”.
Before / after the last deploy
The most useful comparison isn't “this week against the previous one”: it's since the last deploy against before. The “Since the last deploy” section puts side by side, URL by URL, the median of the 24 hours before and that of the 24 hours after the last production deploy.
- It takes at least 5 measurements on each side, otherwise the median is only a coincidence: “Not enough measurements on both sides to compare — it takes at least 5 per URL, in the 24 hours before and after.”
- A URL is said to have slowed down or sped up when the gap exceeds both 20% and 50 ms. Both, because going from 10 to 13 ms is measurement noise, and going from 800 to 900 ms is only 12 percent. Otherwise, stable.
- A URL missing on one side (added yesterday) is left out rather than compared with zero.
- Slowdowns first, the strongest at the top: “2 pages slowed down since this deploy.”, with
420 → 640 msand the percentage. Or “No page slowed down.”
The comparison requires a recorded deploy: webhook or fingerprint detection.
The rest of the page
- Real vitals and Visitor errors, over the same window, if the snippet is in place: see Real vitals and Visitor errors.
- CSV: the link at the top exports the window's measurements, see Exports.
What triggers an alert
The Performance page doesn't alert by itself. 3 mechanisms do: the latency threshold set on a URL (“took 2,300 ms to respond (threshold: 1,500 ms)”), the latency anomalies (when a page drifts from its rhythm), and the performance budget measured by PageSpeed after every deploy.
Limits and plans
| Discover | Pro | Pro Plus | |
|---|---|---|---|
| Available windows | 24 h, 7 days | 24 h, 7 days, 30 days | 24 h, 7 days, 30 days, 90 days |
| Measurements kept | 7 days | 30 days | 90 days |
| “Normal” band | Yes | Yes | Yes |
| Anomaly dots on the curve | No | Yes | Yes |
See the plans and Data and retention.
Troubleshooting
Why does the page say “No measurement yet”?
No URL of kind HTTP, form or journey has been checked yet. Add a URL or wait for the next run.
Why is the before/after comparison empty?
No production deploy recorded, or fewer than 5 measurements on one side: on a 30-minute plan, 24 hours make 48 runs, but a deploy from an hour ago only has 2 “after”.
Latency threshold
Turn a response time that is too long into a failure, hence an alert, hence an incident.
A page that takes 3 seconds to start responding isn't “up” for the person waiting for it. Yet the HTTP check only looks at the status. The latency threshold puts a limit in milliseconds on a URL: beyond it, the run fails as for an error. It's the difference between seeing the slowness on the Performance page afterwards, and being told during.
What PostShip checks
On every run of an HTTP target, PostShip measures the TTFB — the time between sending the request and the first byte of the response, redirects included, from its servers. This measurement is always recorded and feeds Performance.
With a threshold set, the rule is simple: if the measured TTFB exceeds the threshold, the run carries the gap ttfb_depasse:<threshold>:<measurement> and its verdict is fail. An empty or null threshold does nothing.
What it measures, and what it doesn't: the TTFB says how long your server takes to start responding — page generation, database, cache miss. It says nothing of the rendering in the browser; for that, there are the real vitals and the performance budget.
Set it up
On the URL's detail (Project → URLs → the URL), “Latency threshold” panel:
- Enter a value in the Milliseconds field: between 50 and 60,000, in steps of 50. The field suggests 800.
- Click “Save”. The panel confirms: “Alert beyond 800 ms.”
- To remove the threshold, empty the field and save: “Latency threshold removed.”
Outside these bounds, saving is refused: “A threshold between 50 and 60,000 ms.”
The threshold is specific to each URL. A home page served by the CDN and a dashboard generated on demand don't have the same normal, and a global threshold would force one of the two to stay quiet or to scream.
What triggers an alert
| Code | Screen sentence | Alert sentence |
|---|---|---|
ttfb_depasse:800:1243 | The page took 1243 ms to respond, beyond the 800 ms threshold. | https://acme.fr/ took 1243 ms to respond (threshold: 800 ms). |
The run's fingerprint keeps the threshold but not the measurement: ttfb_depasse:800:1243 then ttfb_depasse:800:1301 are the same outage. Without that, a slow page would have alerted on every cycle, 5 minutes out of 5. You receive an alert at the crossing — after the confirmation set for the project — then “Recovered” when the page goes back under the threshold.
An overrun counts like any HTTP failure: it opens an incident, appears on the status page and costs 10 points on the Ship Score if it happens on a deploy (40 if the page is part of the payment pages).
Limits and plans
The latency threshold is available on all plans, on any HTTP target. What changes with the plan is the frequency of the measurement: every 5 minutes on Discover, every 2 on Pro, every minute on Pro Plus, where the 30-second probe reruns the full measurement as soon as a page crosses the threshold. To be told of an unusual slowness without setting a threshold — a page that drifts from its rhythm at that hour — see Latency anomalies (Pro and Pro Plus).
Troubleshooting
Why is PostShip's TTFB higher than my browser's?
PostShip measures from its servers, with a fresh connection on every run (no connection kept open, no cache), and the time includes the followed redirects. Compare with the usual value shown on Performance, not with your Network tab. On Pro Plus, Regions measures from 5 continents to tell a local slowness from a server slowness.
Why didn't the alert go out when the page exceeded the threshold?
Either the project's confirmation requires 2 or 3 failures in a row (Project → Alerts → Rules), or a silence or quiet hours are active. The URL's detail shows the failing run in both cases.
Does the threshold apply to a payment journey?
No. The steps of a journey are checked with an expected 200 status and the payment pages' assertions, without a latency threshold. Set the threshold on the matching page added as an HTTP target.
Latency anomalies
Available on the Pro and Pro Plus plans.
An alert when a page becomes abnormally slow for that hour of the week, with the exact formula.
A fixed threshold on response time lies twice: it screams on a site slow by nature, and it stays quiet on a fast site that just tripled. What we want to know is whether this run drifts from what this page usually does at this moment: Monday 9 am has nothing to do with Sunday 3 am. Latency anomalies compare each successful run with the page's habit at that hour of the week, and only alert on entering the anomaly.
The baseline
Every night, PostShip recomputes for each URL of kind HTTP, form or journey, and for each of the 168 hours of the week (Monday 9 am, Tuesday 9 am…, in UTC), 2 numbers on the successful runs of the last 14 days:
- the median TTFB;
- the median absolute deviation (MAD): the median of the deviations from the median.
Median and MAD rather than mean and standard deviation, because a baseline must resist the anomalies it serves to detect: 3 spikes in the window don't move the median, they would have doubled the standard deviation. A slot with fewer than 3 successful runs has no line; a run whose slot is empty compares with the hour before, failing that the hour after, never further: 2 hours away, we're no longer sure to be in the same traffic regime.
This rhythm is visible on each URL's page, “rhythm of the week”: the hour-by-day grid of the median, in UTC. You read there the night that sleeps, the Monday 9 am that suffers, the 3 am backup.
The formula
For a successful run of TTFB t, with the median m and the MAD of its slot:
z = (t − m) / (1.4826 × max(MAD, 20 ms))1.4826 is the constant that turns a MAD into a standard deviation for a normal distribution: the score then reads like a classic z. The 20 ms floor is the network noise we can't tell from a real change: a very stable site has an almost zero MAD, and dividing by zero would make any deviation infinite.
A run is an anomaly when it crosses all 4 guards, each against a known false positive:
| Guard | Value | Against what |
|---|---|---|
| Baseline well enough fed | n ≥ 5 runs | A median of 4 points is that of a handful of runs |
| Statistically rare | z > 4 | One chance in 30,000 under a normal distribution; at z = 3, with a run every 5 minutes, it would ring every day |
| At least twice as slow | t ≥ 2 × m | On a very stable site, +150 ms make z = 5: rare, but not “slow” |
| Slow enough in absolute terms | t > 300 ms | 50 ms going to 150 ms is 3 times more and nobody cares |
A run faster than usual is never an anomaly: z is negative, and a CDN waking up isn't an alert. Neither is a failing run: the TTFB of a 500 page measures an outage, already flagged elsewhere.
What triggers an alert
On entry only. A page slow for an hour is 12 abnormal runs: the first alert says everything, the 11 following ones say nothing more. PostShip looks at whether the previous run already carried an anomaly and stays quiet as long as it lasts. The return to normal doesn't make an alert either: silence is the message.
The alert borrows the “Content changed” channel of URL alerts, with its own sentence, and it goes ahead of a content mutation of the same run because it's more urgent:
3× slower than usual at this hour (1,850 ms against 600 ms normally)The ratio is rounded to the tenth (“2.5×”). The alert follows the others' rules: silence, quiet hours, maintenance, and the “Content changed after a deploy” box for email. See Email, Discord, Slack and Rules.
Runs following a deploy are not evaluated: a deploy makes pages slower while the cache fills, and that slowness has a known cause.
Where to see it
- On the Performance page: the “normal” band of each curve (median ± 2 robust deviations, narrower than the alert threshold, on purpose) and a red dot at each run recorded as abnormal. See Performance.
- On the URL's page: the rhythm of the week.
- In the probable cause: an anomaly in the hour before the outage is worth +40 to the “Saturation” hypothesis.
Set it up
Nothing to set: detection is active as soon as the plan allows it, on all HTTP, form and journey URLs, as soon as their baseline exists. For a fixed threshold chosen by you, see the latency threshold: a failure from a value, on every run.
Limits and plans
| Discover | Pro | Pro Plus | |
|---|---|---|---|
| Rhythm of the week and “normal” band | Yes | Yes | Yes |
| Detection and alert | No | Yes | Yes |
See the plans.
Troubleshooting
Why no alert when my page doubled?
Look at the 4 guards: under 300 ms, no alert; with a wide MAD (a site that swings a lot), doubling doesn't make z > 4. Or the page was already slow on the previous run: the alert only went out on entry.
Why is the baseline empty on a recent URL?
It's computed at night, over 14 days, with at least 3 successful runs per hourly slot. A URL added today will have its first slots tomorrow morning, and a full rhythm in 2 weeks.