Search
Varnish Cache Plus

Stale

Description

Stale object API. This API allows for a safe and high performance Stale-If-Error implementation.

Note: Using a Stale-If-Error implementation that depends on abandoning backend fetches and restarting is unsafe for sites which serve moderate to high levels of traffic. This is because the abandon-restart loop can cause significant amounts of request serialization since Varnish will only allow a single request per object to hit the abandon-restart loop at a time.

Note: A bug in vmod_stale version 6.0.6r3 can cause it to function unsafely on hit-for-miss objects. This has been resolved in versions 6.0.6r4 and later.

Stale If Error

First, make sure a suitable beresp.keep value is set. This value determines the Stale-If-Error period. beresp.ttl and beresp.grace do not need to be changed. Remember, the lifetime of an object is ttl + grace + keep.

sub vcl_backend_response {
    # Keep these values unchanged
    set beresp.ttl = ...;
    set beresp.grace = ...;

    # Add a 7 day Stale-If-Error period
    set beresp.keep = 7d;
}

Next, put the following VCL at the top of your sub vcl_backend_* section.

import stale;

sub stale_if_error {
    if (beresp.status >= 500 && stale.exists()) {
        # Tune this value to match your traffic and caching patterns
        stale.revive(20m, 1h);
        stale.deliver();
        return (abandon);
    }
}

sub vcl_backend_response {
    call stale_if_error;
}

sub vcl_backend_error {
    call stale_if_error;
}

Make note of the stale.revive(TTL, grace) call above. The values used should be large enough to limit backend traffic and prevent a thundering herd problem when the backend comes back online. It also needs to be small enough to allow Varnish to be responsive to when your backend does come back online.

Using beresp.keep is entirely optional, beresp.grace can also be re-leveraged for Stale-If-Error. If using grace, the client will immediately get a stale object instead of waiting for an error to trigger the stale object delivery. If disabling grace via req.grace, the grace behavior will match Stale-If-Error. In all cases, if a stale object exists, no fresh error response will reach the client.

API

Note: The following API only works in a backend context (sub vcl_backend_*). Using the API outside of a backend context will result in a request failure.

exists

BOOL exists()

Does a stale object exist?

Arguments

None

Returns

true if a stale object exists, otherwise false.

deliver

BOOL deliver()

Deliver the stale object to the client. Must be used with return(abandon). If normal return(deliver) is done, the stale object will not be returned. If the request is a bgfetch or there is no client waiting, this is a no-op.

Arguments

None

Returns

true if the stale object can be delivered, otherwise false. A bgfetch will return false.

revive

VOID revive(DURATION ttl, DURATION grace)

Revive the stale object with a new ttl and grace. The original time of expiration is maintained. The object will not revive beyond its initial beresp.ttl + beresp.grace + beresp.keep. The leftover time to expiration is stored back as the keep value.

Arguments

  • DURATION ttl - the new TTL value. If less than or equal to 0s, the revive call does nothing.

  • DURATION grace - the new grace value. If less than 0s, the value is rounded upto 0s.

Returns

Nothing

rearm

VOID rearm(DURATION ttl, DURATION grace, DURATION keep)

Set a new ttl, grace, and keep. These values overwrite any existing values and can extend the time of expiration to any point in time. A value of 0s clears the value out. Negative values keep the existing value in place.

Arguments

  • DURATION ttl - the new TTL value. A negative value keeps the previous expired TTL value.

  • DURATION grace - the new grace value. A negative value keeps the previous grace value.

  • DURATION keep - the new keep value. A negative value keeps the previous keep value.

Returns

Nothing

get_status

INT get_status()

Get the response status code from the stale object.

Arguments

None

Returns

The response status code from the stale object. 0 if the stale object does not exist.

get_header

STRING get_header(STRING name, STRING default)

Get a response header from the stale object.

Arguments

  • STRING name - The header name.

  • STRING default optional - The value to return if the header is not found or the stale object does not exist. Defaults to an empty false value.

Returns

The header value if it exists, otherwise default.

get_ttl

DURATION get_ttl(BOOL remaining = true)

Get the TTL value from the stale object.

Arguments

  • BOOL remaining optional - Get the remaining TTL value. Defaults to true.

Returns

The TTL value from the stale object. When remaining is true and the object is expired, this value is negative.

get_grace

DURATION get_grace(BOOL remaining = false)

Get the grace value from the stale object.

Arguments

  • BOOL remaining optional - Get the remaining grace value. Defaults to false.

Returns

The grace value from the stale object. When remaining is true and the object is past grace, this value is negative.

get_keep

DURATION get_keep(BOOL remaining = false)

Get the keep value from the stale object.

Arguments

  • BOOL remaining optional - Get the remaining keep value. Defaults to false.

Returns

The keep value from the stale object. When remaining is true, this value is the total time to expiration of the stale object.