Skip to content

Give the derived duration budget room to be a ceiling - #76

Merged
arberx merged 1 commit into
mainfrom
fix/duration-headroom
Sep 7, 2026
Merged

arberx merged 1 commit into
mainfrom
fix/duration-headroom

Conversation

@arberx

@arberx arberx commented Sep 7, 2026

Copy link
Copy Markdown
Member

SCALED_PAGES_PER_SECOND was 2.5, the arithmetic rate at the default concurrency of 5 against a two-second origin. That is a plausible average and a bad ceiling.

Measured on a ~8,700-page production site: 7,351 pages in 58 minutes, or 2.11 pages per second including parse, redirects and retries. The derived clock expired at 84% of a crawl that was making steady progress, and the run was reported max-duration even though the page budget had never bound. That is the same silent truncation the budget scaling exists to remove, moved from bytes to the clock.

The constant is now 1 page per second, for the reason SCALED_BYTES_PER_PAGE is already generous, in its own words: the budget is a ceiling, not an allocation, so over-provisioning costs nothing while under-provisioning truncates a healthy crawl.

maxPages budget before budget after need at the measured 2.11/s headroom
500 3 min 8 min 4 min 2.1x
5,000 33 min 83 min 39 min 2.1x
8,700 58 min 145 min 69 min 2.1x

A stated maxDurationMs is still honoured exactly, requestDelayMs still adds on top, and the flat default remains the floor for small crawls.

The test pins the headroom relationship against the observed rate rather than the constant itself, so it keeps meaning something if the constant moves again. Verified it fails with the old 2.5 restored. 626 tests pass; typecheck, lint, e2e clean.

Minor bump 7.1.0 to 7.2.0; crawl engine 2.2.0 to 2.3.0 (shape unchanged, semantics changed).

🤖 Generated with Claude Code

SCALED_PAGES_PER_SECOND was 2.5, the arithmetic rate at the default
concurrency of 5 against a two-second origin. That is a plausible average
and a bad ceiling.

Measured on a ~8,700-page production site: 7,351 pages in 58 minutes, or
2.11 pages per second including parse, redirects and retries. The derived
clock expired at 84% of a crawl that was making steady progress, and the
run was reported max-duration even though the page budget had never bound.
That is the same silent truncation the budget scaling exists to remove,
moved from bytes to the clock.

The constant is now 1 page per second, for the reason SCALED_BYTES_PER_PAGE
is already generous: the budget is a ceiling, not an allocation, so
over-provisioning costs nothing while under-provisioning truncates a
healthy crawl. An origin can now be twice as slow as that measurement and
the crawl still ends on its page budget.

A stated maxDurationMs is honoured exactly, requestDelayMs still adds on
top, and the flat default remains the floor for small crawls. The test
pins the headroom relationship against the observed rate rather than the
constant, so it keeps meaning something if the constant moves again.

Engine 2.2.0 to 2.3.0: shape unchanged, semantics changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@arberx
arberx merged commit 604f39c into main Sep 7, 2026
4 checks passed
@arberx
arberx deleted the fix/duration-headroom branch September 13, 2026 23:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant