From e15bda023d8c5d1b105dc4ebffb9e671781f07d4 Mon Sep 17 00:00:00 2001 From: Nimrod Teich Date: Sun, 23 Aug 2026 13:41:39 +0300 Subject: [PATCH] docs(cli): --chain-tracker-poll-divisor allows a cadence slower than block time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit smart-router#323 widened the range from [1,8] to [0.25,8]. At 0.25 the tracker polls once per four block times — 8x below the built-in cadence, and the relief that matters on a fast chain. The old floor of 1 was justified by the claim that below it the avgBlockTime-derived windows start to bind. They do not: the staleness window is max(10 x avgBlockTime, 2s) and does not move with this flag — the flag moves the other side of that comparison. Both common cases stay well inside it; the exposure is the seam where an upstream trips the traffic gate and then goes quiet, refreshed by neither polls nor relays. That seam is a property of the product of this flag and the gate's skip budget, so the router warns per chain at startup instead of refusing to start. Documented verbatim, with what to do about it, so the line is read as guidance rather than a failed boot. --- docs/reference/cli.md | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 0c4d65b..480407f 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -76,7 +76,7 @@ and confirm what is live via `HashPolling` in `GET /debug/endpoint-state`. | Flag | Default | Description | | --- | --- | --- | | `--enable-fork-detection` | `false` | Turn on block-hash polling (reorg detection on upstreams). Off by default — the larger of the per-pod savings. | -| `--chain-tracker-poll-divisor` | `2` | The tracker polls every `avgBlockTime ÷ divisor`. `1` halves the polling rate. Allowed `[1,8]`; out-of-range reverts to the default. | +| `--chain-tracker-poll-divisor` | `2` | The tracker polls every `avgBlockTime ÷ divisor`. `1` halves the polling rate; `0.25` — one poll per **four** block times — cuts it eightfold. Allowed `[0.25,8]`; out-of-range reverts to the default. See [Polling slower than the chain](#polling-slower-than-the-chain). | | `--shared-state` (with `--cache-be`) | `false` | Share poll observations across router replicas through the cache, so an upstream is polled about once per interval **fleet-wide** rather than once per pod. See [Cache & shared state](#cache-shared-state). | The tracker also skips a poll whenever something else has already kept the upstream's @@ -86,6 +86,42 @@ poll another replica made. Skipped ticks show up on `source`, so `requests_total` falling while `gate_skips_total` rises is the relief working, not the tracker stalling. +### Polling slower than the chain + +A divisor below `1` polls less often than the chain produces blocks, which is where +the relief is on a fast chain. Measured requests/min per endpoint: + +| Chain | `2` (default) | `1` | `0.5` | `0.25` | +| --- | --- | --- | --- | --- | +| Aptos | 600 | 300 | 150 | 75 | +| Solana | 300 | 150 | 75 | 37.5 | +| Base | 60 | 30 | 15 | 7.5 | +| Ethereum | 9.2 | 4.6 | 2.3 | 1.2 | + +What bounds the low end is the staleness window — `max(10 × avgBlockTime, 2s)`, past +which an observation stops counting for consensus, the tip reads unknown, and the probe +scores a healthy upstream not-alive. The window does **not** move with this flag; the +flag moves how long a tip can go unrefreshed, the other side of that comparison. Both +common cases stay well inside it: + +- **Idle upstream** — nothing but its own poll refreshes the tip, so the gap *is* the + interval: 4 × `avgBlockTime` at `0.25`, against a 10× window. +- **Served upstream** — relays refresh the same tip, so traffic bounds the gap. + +The seam is between them: an upstream that trips the traffic gate and *then* goes quiet +is refreshed by neither, and the worst-case gap becomes `(maxRelaySkips + 1) × interval` +— 20 × `avgBlockTime` at `0.25`. That is a property of the **product** of this flag and +the gate's skip budget, not of either alone, so the router warns once per chain at +startup rather than refusing to start: + +``` +WRN poll cadence can outrun the staleness window when the traffic gate skips + pollInterval=60s worstCaseGapBetweenPolls=5m0s stalenessWindow=2m30s maxRelaySkips=4 +``` + +It is a line to read, not a failure — the configuration is safe for both common cases. +If you see it on a chain with bursty traffic, step back toward `0.5` or `1`. + ## Consistency tuning | Flag | Default | Description |