The README example uses a 10 minute TTL. On a miss the loader runs, and the entry is stored with a backend TTL of 12 minutes: the soft TTL plus the widest stale window (2 minutes).
1The first call loads and stores
2Fresh: a plain cache hit
3Refresh-ahead: refresh before expiry
4Stale-while-revalidate
5Past that window, the loader runs
6Stale-if-error: availability first
7After 12 minutes the entry is gone
←→ step · space play
All steps as text
The first call loads and stores. The README example uses a 10 minute TTL. On a miss the loader runs, and the entry is stored with a backend TTL of 12 minutes: the soft TTL plus the widest stale window (2 minutes).
Fresh: a plain cache hit. Before refresh-ahead starts, a call just returns the cached value. Nothing else happens.
Refresh-ahead: refresh before expiry. WithRefreshAhead(0.8) means: once 80% of the TTL has passed (8 minutes here), refresh in the background and return the still-valid value at once. A hot key never expires under load.
Stale-while-revalidate. After the 10 minute expiry, WithStaleWhileRevalidate(30s) keeps serving the stale value for 30 seconds while one background load refreshes it.
Past that window, the loader runs. After the stale-while-revalidate window, the call goes to the single-flight loader like a miss. If the loader works, the caller gets the new value.
Stale-if-error: availability first. If that loader call fails, WithStaleIfError(2m) returns the stale value instead of the error, as long as it is within 2 minutes past expiry. This trades staleness for availability.
After 12 minutes the entry is gone. The backend dropped the entry at its 12 minute TTL. A call now is a plain miss, and if the loader fails, the caller gets the error.
Remember stores values inside a small JSON envelope (born, soft expiry, missing) so the staleness data survives any value codec. The diagram leaves out WithNegativeTTL, which caches a loader’s ErrNotFound for a while, and WithJitter, which adds ±10% random noise to the stored TTL so keys written together do not all expire at once.