Stale document previews: versioned cache keys and safe publication
Design preview cache keys and publication rules so a fast cached response does not show silently outdated content.

A preview must identify the source version that produced it. Use that identity in the cache key and guard updates to any “current preview” pointer. Otherwise, a delayed conversion for revision A can overwrite the preview for revision B even when the source document itself is up to date.
Give the preview an explicit source identity
Include the business document version or immutable source digest, output format, and rendering options that affect the result. If changing fonts or converter versions can change output, decide whether those dependencies belong in the key or trigger an explicit regeneration. A cache keyed only by filename will collide across copies and survive renames unpredictably. Scope private document results by the appropriate tenant or access boundary. Content identity and authorization are separate concerns: knowing the cache key should never grant permission to retrieve its object.
preview identity = source version + output mode + rendering options
preview metadata = document ID + source version + renderer revision
current pointer = only a preview matching the intended current versionThese are design ingredients, not an instruction to concatenate untrusted strings into a path. Normalize and validate the fields, and retain ordinary access checks when serving cached objects. Include renderer or font changes in regeneration policy when they can affect the result.
Distinguish a content-addressed immutable result from an endpoint named current. The former can often be cached for a long time under the correct private-access rules. The latter represents a changing selection and needs validation or cache controls consistent with that promise. A browser refresh is not a dependable invalidation protocol.
When a user reports a mismatch, compare the document version selected by the page, the source version recorded on the preview, and the URL actually served by the browser. Those three observations localize the problem: wrong selection, late publication, or a stale downstream response. Purging every cache may conceal the defect without identifying which relationship broke.

Reject late results from the current pointer
A conversion started for version A may finish after version B becomes current. Store its result as a preview of A, and update any current preview pointer only through a guard that checks the source version. Otherwise, an old worker can overwrite a newer result. Keep the relationship visible in metadata and diagnostics. When the current preview is not ready, show preparation status or a clearly labeled older snapshot according to policy. Never silently attach a stale preview to the newest version label merely to avoid an empty state.
Coordinate the browser and service caches
Versioned URLs can support long lived caching for immutable output, while mutable current endpoints need deliberate validation or cache control. Review intermediary caches, authenticated download handlers, and browser behavior together. A server cache purge alone may not invalidate an already cached browser response. Conversely, disabling every cache can create unnecessary conversion load. Use the HTTP semantics supported by your deployment and verify private response handling. Avoid placing sensitive preview URLs into shared caches unless the access model and response directives explicitly support that behavior.
Race two revisions and inspect the served version
Open a contract preview for revision A, then save revision B with a conspicuous test change. Delay A's conversion until B's preview has finished, and refresh from an existing browser tab as well as a new session. Confirm that the current view displays B, historical links still identify A, and no response mixes B's title with A's pages. Repeat after a rendering configuration change. This controlled race exercises worker publication and browser caching together, where many apparently random stale preview reports originate.
- Record source version and renderer configuration with every generated preview.
- Guard updates to current preview pointers against delayed jobs.
- Label historical or temporarily stale results explicitly.
- Verify authorization even when the cached object already exists.
- Define cleanup rules for superseded previews without removing retained historical versions.



