Every gap, and why.
The coverage report lists when capture stopped. This is why it stopped — for each interruption, what we observed, and whose fault it was. Including ours.
Capture interruptions
Every interruption over five minutes, newest first. These are the same windows the coverage report counts against us — an upstream cause does not exempt a gap from our coverage figures, because the data is missing either way.
Deribit returned HTTP 503 Service Unavailable continuously for the whole window. Capture resumed within a minute of the last refusal. The L2 book daemon separately exhausted its reconnect budget and was restarted by systemd 270 times during the same period; that is our defect and is being fixed, but it did not lengthen this interruption — the exchange was refusing every request throughout, so there was nothing to capture, and chain collection resumed as soon as the 503s stopped.
evidence — 3,456 x 503 responses in the window, sustained at roughly 87 per minute from 09:00Z to 09:35Z with no gap, plus 204 x 429 and 5 x 403. Last 503 at 09:35Z; first snapshot written 09:36Z. The book daemon logged book_daemon_max_reconnects_exhausted and recovered at 09:36:17Z with book_subscriptions_refreshed count=1826.
Deribit closed every one of our websocket connections at the same second, without a close frame. That alone is routine and recoverable. What turned it into a ten-minute interruption is our reconnect loop: the backoff counter resets on a successful CONNECT rather than on a connection that survives, so a socket that establishes and immediately dies restarts the delay at one second indefinitely. It never escalated. Two hundred reconnect cycles followed, each re-subscribing every channel, and Deribit answered 820 times with 429 Too Many Requests. Capture resumed when the cycle settled. This is the third rate-limit incident of the same family after 2026-07-14 and 2026-08-13; the fix made in August taught the REST retry path to honour Retry-After and did not touch the websocket reconnect path, which is where this one happened.
evidence — 820 x 429 Too Many Requests and no 503 responses at all, so the exchange was serving other traffic and refusing ours. 200 x deribit_ws_disconnected paired with 200 x deribit_ws_connecting, every one logged attempt=0, which is the reset. First disconnections all share the timestamp 06:01:37Z with error 'no close frame received or sent'.
Deribit returned HTTP 503 Service Unavailable.
evidence — 1,205 x 503 responses in the window, alongside 85 x 429.
Deribit returned HTTP 503 Service Unavailable. The longest interruption on record.
evidence — 6,666 x 503 responses in the window, alongside 516 x 429.
We exceeded Deribit's request rate limit again and were throttled with HTTP 429. This is a recurrence of 2026-07-14, from the same line of code: the retry path waited 0.1s, 0.2s, 0.4s for every error including a throttle, and ignored the Retry-After header telling us how long to wait. Retrying a rate limit after 100ms is what keeps it tripped, so our own traffic sustained the outage a second time. The July incident named this defect and nothing was changed; publishing a cause is not the same as fixing it. The retry path now honours Retry-After, with a one-second floor and a sixty-second ceiling, for 429 only — a 503 means the exchange is down rather than annoyed, and still retries fast.
evidence — 306 × 429 Too Many Requests in the window, with 136 websocket reconnects. No service restart.
Deribit returned HTTP 503 Service Unavailable.
evidence — 1,566 × 503 responses in the window.
Deribit returned HTTP 503 Service Unavailable.
evidence — 1,053 × 503 responses in the window.
Deribit returned HTTP 503 Service Unavailable.
evidence — 459 × 503 responses in the window.
We exceeded Deribit's request rate limit and were throttled with HTTP 429. The collector's retry path had no backoff proportional to the throttling, so it kept requesting and kept being refused — our own traffic sustained the outage. Capture recovered and failed again between retries, so it is measured as two separate interruptions rather than one continuous outage.
evidence — 510 × 429 Too Many Requests, and 300 reconnect attempts, in the window.
We exceeded Deribit's request rate limit and were throttled with HTTP 429. The collector's retry path had no backoff proportional to the throttling, so it kept requesting and kept being refused — our own traffic sustained the outage. Capture recovered and failed again between retries, so it is measured as two separate interruptions rather than one continuous outage.
evidence — 510 × 429 Too Many Requests, and 300 reconnect attempts, in the window.
Deribit returned HTTP 503 Service Unavailable. Longest to date.
evidence — 4,347 × 503 responses in the window.
Deribit returned HTTP 503 Service Unavailable.
evidence — 1,107 × 503 responses in the window.
Deribit rejected requests with HTTP 403 Forbidden. The rejection was at the edge rather than the API, and cleared without action from us.
evidence — 126 × 403 responses in the window.
Deribit returned HTTP 503 Service Unavailable.
evidence — 378 × 503 responses in the window.
Deribit returned HTTP 503 Service Unavailable to every request.
evidence — 1,674 × 503 responses on /public/get_instruments in the window.
Not established.
evidence — Falls two hours before the retained journal begins (2026-05-13T15:53Z).
Not established.
evidence — Predates collector log retention.
Not established. The start time matches six later interruptions that were confirmed as exchange outages, but a matching signature is not evidence and this one is not claimed as upstream.
evidence — Predates collector log retention.
Not established.
evidence — Predates collector log retention.
Not established.
evidence — Predates collector log retention.
Not established.
evidence — Predates collector log retention (logs begin 2026-05-13T15:53Z).
Service incidents
Failures that cost no data, so they appear in no coverage figure. They are here because a record containing only the failures that happen to show up in a metric is a selected one.
The six-hourly job that regenerates the public evidence artifacts was a bare command in the crontab and did not source the service environment, so it had no database or object-store credentials. Rather than failing, it measured nothing and published an empty coverage report over a complete one. The public coverage page showed no coverage for fourteen hours.
Impact. Display only. Capture ran normally throughout — 842 BTC snapshots at a 60-second median with no interruption over five minutes — and no data was lost or altered. One visitor loaded the page during the window.
Fix. The job refuses to start when a source is unreachable, refuses to write a report that measured nothing, and leaves the previous artifact serving. It now runs through a wrapper that loads the environment, as every other scheduled job already did.