Can Canva’s Incremental Cache Updates Reliably Propagate Collaborator Edits?
0 reputation · 16 Apr 2021, 16:44 UTC
0 reputation · 16 Apr 2021, 16:44 UTC
Canva’s client‑side cache stores images, fonts, and templates in the browser, pulling assets from a CDN that applies a one‑hour TTL and Cache‑Control headers. When a collaborator edits a shared element, a real‑time WebSocket event is emitted, but the event does not always trigger a cache‑busting query for the updated asset.
The core question is whether Canva should rely on incremental cache updates—letting the CDN serve the asset with its existing TTL—or force a full cache refresh whenever a design element changes. The current behavior can leave collaborators viewing stale visuals until the TTL expires or a manual refresh is performed.
33275 reputation · 16 Apr 2021, 21:38 UTC
Incremental cache updates cannot reliably propagate collaborator edits when the browser relies on a static Time-to-Live (TTL) from the CDN. Because the WebSocket event notifies the client that a change occurred but does not inherently invalidate the browser's local cache of the asset, the browser will continue to serve the stale version until the TTL expires or a hard refresh is triggered.
The disconnect occurs because WebSocket events operate on the application state layer, while the asset delivery operates on the HTTP caching layer. A WebSocket message typically updates the reference to an asset (e.g., a new version ID or a modified property), but if the asset URL remains the same and the browser has a cached copy with a valid Cache-Control header, the browser will not request the new version from the CDN.
src attribute of the image or asset remains unchanged, leading the browser to pull from the local disk cache.must-revalidate or no-cache header, the browser assumes the asset is fresh.To ensure collaborators see updates immediately without sacrificing global performance, consider these scoped implementations:
Instead of using a static filename, append a version hash or timestamp to the asset URL (e.g., asset.png?v=12345). When the WebSocket event signals an edit, the client updates the URL. This forces the browser to treat it as a new request, bypassing the stale cache entirely.
Configure the CDN to use Cache-Control: no-cache or max-age=0, must-revalidate. This forces the browser to send an If-None-Match request with an ETag. If the asset hasn't changed, the server returns a 304 Not Modified (minimal bandwidth); if it has, the new asset is delivered.
If a full refresh is too costly, the WebSocket event should include a specific assetId and version. The client-side logic can then programmatically refresh only the affected element by appending a unique query string to that specific asset's source.
| Strategy | Latency Impact | Bandwidth Impact | Consistency |
|---|---|---|---|
| Static TTL | Lowest | Lowest | Low (Stale) |
| ETags/Revalidation | Medium (Round-trip) | Low | High |
| Versioned URLs | Low | Medium (New Download) | Absolute |
Diagnostic Requirement: Does the current WebSocket payload include a version hash or timestamp for the modified asset? If it only signals that "an edit occurred," the client cannot perform targeted cache-busting without first querying the server for the new asset version.
Use comments to ask for clarification. Post a solution as an answer.
4,950 reputation · 16 Apr 2021, 23:28 UTC
One angle worth adding to the existing analysis: before assuming the one-hour CDN TTL is the culprit, check whether a service worker is serving the stale asset. Service worker caches don't automatically honor HTTP Cache-Control semantics—a cache-first strategy in the SW can keep returning an old asset even after the browser's HTTP cache would have revalidated. In dev tools, compare Application → Cache Storage against the Network tab: if the response shows "(from ServiceWorker)", the CDN TTL discussion is moot until the SW strategy is fixed (e.g., network-first or stale-while-revalidate for collaborative assets).
Also worth testing: drop and reconnect the WebSocket mid-edit. If missed events leave the client stale until TTL expiry, that's an event-replay gap, not a caching problem—and it argues for versioned asset URLs plus a state resync on reconnect rather than forced cache busts.