Reference · Lesson 2

Timeouts and deadlines

How long to wait, and how to share one time budget across hops.

The rules

Picking a timeout

false-timeout budgetpercentilelab PayCo (synthetic, seed 1)
50%p5040 ms (never do this)
10%p9064 ms
1%p99206 ms (smallest within 1%: 178 ms; 150 ms is 1.004%, just over)
0.1%p99.91816 ms
too shorttoo long
false timeouts → unknown outcomes, errors, retries, extra load on a slow serverstuck users, threads and connections held while something is truly broken

Contracts

functionmust
withTimeout(ms, work)reject with TimeoutError after ms even if work ignores its signal (race them) · abort the AbortSignal handed to work · return the work's result unchanged · clear the timer on every path
Deadline.remaining()ms left until the deadline, never negative
withDeadline(d, cap, work)wait min(cap, remaining) · nothing left → TimeoutError without calling work
toolwhat it gives you
AbortController.signal to hand out; .abort(reason) flips signal.aborted and fires 'abort'
signal.reasonwhatever you passed to abort() (here a TimeoutError)
try … finallythe place to clear the timer

Across machines: send the remaining duration, not an absolute time (clock skew). Servers should check whether the caller already gave up before doing expensive work.

Lab

npm run test:028 tests for src/timeout.ts
TIMEOUT_MS=250 npm run l2Part A: percentiles, false-timeout rate (3 decimals) and a within/OVER verdict for 1% and 0.1% budgets. Part B: your withTimeout against lost messages on the lab network, always at a fixed 30 ms. → results/02-timeouts.json

Sources