A cache can return an expired stored response immediately and start validation in parallel when stale-while-revalidate permits that reuse. The request that encounters the stale entry therefore does not have to inherit origin validation latency, but it can receive representation data older than the normal freshness lifetime.
This is a deliberate shift in the cache contract. Freshness still expires at the configured boundary. The extension adds a separate interval in which stale reuse is permitted while validation proceeds, so response age and request latency become partially decoupled.
Freshness expiry and stale reuse are separate boundaries
Consider this response directive:
Cache-Control: max-age=60, stale-while-revalidate=30The stored response is fresh for its first 60 seconds of age, subject to the HTTP cache age calculation. During that interval, a cache can normally reuse it without contacting the origin.
After freshness expires, stale-while-revalidate=30 permits reuse for an additional 30 seconds. If the cache serves the stale response under this extension, it should attempt validation without blocking that response on the validation result.
The two intervals express different properties:
age 0s 60s 90s
|------------------------------|---------------------------|
fresh reuse stale reuse permitted
during revalidationThe second interval does not extend freshness. It authorizes bounded stale service. That distinction matters for observability and correctness because a response can be legitimately served while already stale.
Validation remains a conditional origin interaction
HTTP validation lets a cache ask whether a stored representation can remain in use rather than transferring the full representation again. A stored validator such as an entity tag can be sent in a conditional request. If the origin reports that the selected representation has not changed, the cache can update stored metadata and continue using the existing body.
With stale-while-revalidate, that interaction moves away from the latency path of the request that triggered it. The client can receive the stale object while the cache performs the conditional exchange separately.
The directive does not define a new validator and does not make validation unnecessary. It changes when a stale response may be used relative to validation.
If the origin returns a replacement representation, later requests can use the refreshed entry. If validation confirms the stored representation, its metadata can be refreshed according to normal cache rules. If validation does not complete before the stale allowance ends, the extension alone no longer authorizes continued stale reuse.
Sparse traffic can expose the end of the stale window
Background refresh is often described as if a cache continuously updates objects as they approach expiry. The protocol mechanism does not require such a scheduler.
A request arriving after the object becomes stale can trigger the asynchronous validation behavior. If no request arrives during the permitted stale interval, no request-driven validation needs to occur.
Suppose the response has a 60-second freshness lifetime and a 30-second stale-while-revalidate allowance. If requests arrive at ages 10, 40, and 95 seconds, the first two can use a fresh response. The request at 95 seconds is outside the extension’s 30-second stale allowance. It cannot rely on stale-while-revalidate to obtain the old response immediately.
Traffic shape therefore affects whether the latency-hiding behavior is exercised. A frequently requested object is more likely to receive a request inside the stale interval than an object with long idle periods.
Concurrent stale requests need not imply concurrent origin work
The protocol permits stale service during revalidation, but it does not require one origin validation request per client request. Cache implementations can coordinate refresh work so that several requests receive the same stale object while one validation is in flight.
That coordination is an implementation property rather than a guarantee supplied by the directive itself. Without such coalescing, multiple requests that arrive after expiry could each cause origin traffic even though clients are receiving stale responses.
This boundary separates two concerns. stale-while-revalidate authorizes stale reuse and describes the intended non-blocking validation behavior. Request collapsing, single-flight refresh, lock granularity, and distributed coordination across cache nodes are separate implementation mechanisms.
A multi-node cache adds another layer. Each node can hold a stored response with its own age and validation state. Unless the cache product coordinates refreshes across nodes, one node’s in-flight validation does not imply that another node suppresses its own origin request.
The directive trades bounded staleness for request-path latency
Without permission to reuse a stale response, a cache that needs validation can place the requesting client behind an origin round trip. With stale-while-revalidate, an eligible stale response can satisfy that request first.
The cost is explicit: the client can observe data older than the freshness lifetime. The maximum extra age attributable to this directive is bounded by its delta value, assuming no other rule independently permits stale reuse.
That condition is important. HTTP has other cache controls and operational policies that can affect stale service. The stale-while-revalidate value is not a universal maximum age for every possible cache behavior; it is the bound attached to this particular permission.
This makes the directive unsuitable as a substitute for an application consistency protocol. A resource whose consumers require validation before every stale reuse needs a stricter cache contract. Latency reduction cannot erase the semantic difference between fresh and stale state.
Revalidation failure is not the same as stale-if-error
A refresh attempt can fail because the origin is unavailable or returns an error. stale-while-revalidate and stale-if-error address different conditions.
The former permits stale service for a bounded interval while validation proceeds. The latter can permit stale service when an error is encountered, within its own configured staleness bound.
A response can carry both directives:
Cache-Control: max-age=60, stale-while-revalidate=30, stale-if-error=300Those values describe distinct permissions. During the first 30 seconds after freshness expiry, stale-while-revalidate can allow immediate stale service while refresh proceeds. Error handling can have a different stale allowance through stale-if-error.
Combining them does not turn the values into one continuous freshness period. Freshness still ends at the max-age boundary, and each stale mechanism applies under its own conditions.
Revalidation directives can close the stale path
HTTP cache directives can impose stricter reuse requirements. In particular, must-revalidate requires successful validation before a stale response is reused.
A response policy should therefore be evaluated as a set of directives rather than by reading stale-while-revalidate in isolation. Adding a stale extension to a response whose other directives prohibit that stale reuse does not create an unconditional escape from the stricter requirement.
This is also a configuration boundary between application intent and intermediary behavior. The origin expresses permissions and restrictions through response metadata; a conforming cache applies those rules when deciding whether a stored response can satisfy a later request.
Cache age remains observable state
Serving stale content in this mode does not reset the stored response’s age merely because validation has started. Until validation or replacement changes the cache state, the object remains stale.
The Age field can expose how long the response has resided in caches according to HTTP age calculations. It is therefore useful when distinguishing a low-latency cache hit from a freshly obtained origin response.
Operational metrics need the same distinction. A high cache-hit ratio can coexist with a meaningful volume of stale responses. Treating every hit as equivalent can hide the consistency side of the latency trade.
Useful cache telemetry can separate fresh hits, stale hits, validation attempts, validation results, origin errors, and requests that block after the stale allowance has expired. Those categories correspond to different protocol states even when clients ultimately receive successful responses.
The stale window is a consistency budget
stale-while-revalidate is most precise when treated as a bounded permission rather than a generic performance switch. It gives a cache room to serve an expired representation while refresh work runs outside the triggering request’s critical path.
The configured delta is therefore part of the resource’s consistency policy. A larger value increases the interval in which request latency can avoid validation, while also increasing the interval in which an expired representation may be returned under this mechanism.
The protocol keeps those properties explicit: freshness has one boundary, stale reuse has another, and validation remains the operation that reconnects cached state to the origin’s current representation.