Deadline Propagation
also called Budget Propagation, Request Deadline, Remaining-Time Passing
Carrying the originating request's absolute deadline through every downstream hop so that each service works with the remaining budget - and refuses work that cannot finish in time, rather than starting it.
A per-hop timeout is a local decision made in ignorance of the whole. If every service in a five-deep chain uses a 3-second timeout, the chain can spend 15 seconds serving a caller who left after 2.
Deadline propagation replaces per-hop durations with an absolute deadline attached to the request and passed downstream. Each service computes the remaining budget, and if the remaining budget is smaller than the work would take, it fails immediately rather than starting.
Why it matters
The majority of load on a saturated dependency is frequently work whose callers have already given up. That work is pure waste, it is generated by the incident itself, and it prevents recovery — the dependency is fully occupied producing responses nobody will read.
Deadline propagation is the mechanism that makes that waste impossible. It is one of the highest-leverage changes available in a distributed system, because it converts a positive feedback loop into a damping one: as latency rises, more requests are rejected early, so offered load falls.
Implementation patterns
- Propagate an absolute deadline, not a duration, so that time already spent is inherently accounted for. gRPC does this natively; HTTP needs a convention and a header.
- Check the budget before starting work, and again before each expensive downstream call.
- Reserve budget for the response path — a service that spends its entire remaining budget on a downstream call has none left to serialise and return.
- Cancel downstream work when the deadline passes, using context cancellation, so the resources are actually released rather than merely abandoned.
- Set the deadline at the edge, from the user-facing latency target, and never let an internal service extend it.
- Reject with a distinct status — deadline exceeded is not the same as an internal error, and conflating them destroys the diagnostic signal.
- Pair it with retry budgets: retries consume the same deadline, so a retry that cannot complete inside the remaining budget must not be attempted.
Industry example
Deadline propagation is standard practice in Google's internal RPC stack and inherited by gRPC, where a deadline is a first-class part of the call rather than a client-side convenience. The SRE literature is explicit that timeouts without propagation are one of the most common contributors to cascading failure, because they permit each layer to independently authorise work that is already pointless.
The complementary observation from the same body of practice: a dependency that degrades rather than fails is more dangerous than one that crashes, and deadline propagation is the primary defence, because it converts "slow" into "fast failure" at every layer.
Failure scenarios
- Per-hop timeouts that multiply, allowing total latency far beyond the user's tolerance.
- A deadline that is propagated but not enforced, so it is metadata rather than behaviour.
- No cancellation, so abandoned work continues to consume the dependency.
- Deadlines extended by an intermediate service "to be safe", which defeats the entire mechanism.
- No reserved budget for the response, producing deadline-exceeded errors on requests that had actually succeeded downstream — which for a non-idempotent operation is a correctness problem, not just a latency one.
- Retries ignoring the deadline, so a request retries after its budget is gone.
Trade-offs
Deadlines cause requests to fail that might have succeeded given more time, and a tight deadline under transient load sheds work that the system could have absorbed. The tuning is real: too tight and availability suffers during ordinary variability; too loose and the mechanism does not engage when it matters.
It also requires end-to-end adoption to work. A single service in the chain that ignores the deadline reintroduces the whole problem, which makes this a platform-level concern rather than a per-team one — best delivered through shared client libraries or a mesh, not through documentation.
The trade is accepting a higher failure rate under load in exchange for bounded latency and the elimination of work-nobody-wants — and at scale that is almost always correct, because unbounded latency is itself a failure, just one that is harder to see.
Interview question
"A downstream service slows from 50 ms to 2 seconds and our whole product degrades. Walk me through what you would add, in priority order, and explain precisely why deadline propagation helps more than raising our timeout or adding capacity."