squirrelscan
GitHub

Time to First Byte: the 600ms and 1000ms thresholds

A server that takes over 600ms to send the first byte, or over 1000ms. squirrel measures TTFB on every fresh fetch.

What TTFB measures

Time to First Byte is the time from the start of the request to the first byte of the response arriving. It covers DNS, the connection, and everything the server did before it started writing: routing, database queries, template rendering, and any upstream call in the way.

It is not a Core Web Vital itself, but every one of them starts after it. A page cannot paint before the HTML arrives, so a slow TTFB moves the floor under Largest Contentful Paint by the same amount. The usual causes are an uncached page rendered per request, a slow query, and a long distance between the visitor and the origin.

What squirrel checks

The rule runs on every crawled page and emits one or two checks:

  • ttfb, skipped with the message TTFB not measured and the reason No TTFB timing data (only available for fresh fetches) when the crawl recorded no TTFB for the page, which is the case for a response served from the audit’s own cache rather than fetched.
  • ttfb, passing with the message Fast server response (Nms) under 600ms, warning with Slow server response (Nms) from 600 to 999ms, and failing with Very slow server response (Nms) at 1000ms or above. The expected value shown is < 600ms on a pass or a warning and < 1000ms on a failure.
  • download-time, at info status with the message Content download: Nms, emitted only when the crawl recorded a download time and a TTFB, since the skip above returns before this check.

The rule uses the measured TTFB alone and never falls back to total load time, which includes the download and would overstate the server’s share. Values are rounded to whole milliseconds.

How to fix it

Serve the page from cache when the content allows it, so the origin is not rendering per request:

Cache-Control: public, max-age=0, s-maxage=600, stale-while-revalidate=86400

That lets a CDN answer from its edge and revalidate in the background. When the page genuinely has to be rendered per request, the work is in the request path: the query that runs without an index, the upstream API called serially, the template compiled on every hit.

The common false positive is a cold start. The first request to a serverless origin after an idle period pays for boot, and a single crawl can catch exactly that request. Re-run the audit before acting on one slow page.

Rule IDperf/ttfb
CategoryPerformance
ScopePer-page
Severitywarning
Weight7/10

Options

OptionTypeDefaultDescription
good_thresholdnumber600Good TTFB in ms
poor_thresholdnumber1000Poor TTFB in ms

Configuration example

[rules."perf/ttfb"]
good_threshold = 600
poor_threshold = 1000

Enable / disable

Disable this rule

[rules]
disable = ["perf/ttfb"]

Disable all Performance rules

[rules]
disable = ["perf/*"]

Enable only this rule

[rules]
enable = ["perf/ttfb"]

enable replaces the default ["*"], so this is the only rule selected. Leave disable out: a rule that matches any disable pattern is skipped even when enable names it. Only an enabled setting under a rule’s own [rule_options] table overrides both lists.

Performance findings ship in every audit next to the SEO, security and agent experience rules. See Core Web Vitals for how an agent works through a report.

References

Check your site

Run squirrel audit https://example.com and open the Performance section of the report. Each page reports its measured server response time. Signed-out local audits need no account and cost nothing. Signed-in audits spend credits.

Type to search…

↑↓ navigate↵ openesc close