UI Monitor script caching
Your project's hosted capture script (litmus.js) is cached — both at Litmus Lab's CDN and in each
visitor's own browser — so that loading it doesn't mean fetching tens of kilobytes on every single
page view. This page explains how that caching works, and specifically how long it takes for a
config change (rotating your webhook secret, or editing privacy/advanced capture settings) to
actually reach your visitors.
Two different caches, two different lifetimes
- Litmus Lab's CDN caches the script for up to a day by default. This is what keeps the script fast and keeps load off our infrastructure — most visitors get it from a nearby CDN location instead of round-tripping to our servers.
- Your visitor's own browser caches it separately, for up to 60 seconds. This is a normal HTTP browser cache, the same kind that applies to images or stylesheets on any site.
These are deliberately different lifetimes, because they answer different questions: "how long can we avoid re-serving this from our own infrastructure" (long) versus "how stale can a page that's just now loading the script be, worst case" (short).
What happens when you change a setting
Any time you rotate your webhook secret or change a capture setting, we immediately purge that one project's script from our CDN's cache — so the next request for it, from anywhere, gets the fresh version rather than waiting out the full day. This typically completes across our CDN within about a minute of the change.
That purge doesn't reach into a visitor's already-loaded browser cache, though — nothing server-side can do that. So the honest, complete picture of when a change takes effect is:
| Situation | When it picks up the change |
|---|---|
| A visitor loading the page for the first time, or after their local 60-second cache has expired | Within roughly a minute of your change (bounded by CDN purge time) |
| A visitor who reloads the page, or navigates to another page with the same embed, within 60 seconds of when they last loaded the script | Not yet — served their own cached copy, no network request happens at all |
| A tab that's already open and has already loaded the script, with no reload or navigation | Not until that tab reloads or navigates somewhere — could be an arbitrarily long time |
The middle and bottom rows are both governed by the visitor's own browser cache, not by anything we can push out from our side — the 60-second browser-side lifetime is what bounds "how stale can a newly loading page be," and there's no equivalent bound for a tab that simply never reloads.
What this means in practice
- Rotating your webhook secret — any already-open tab keeps using the old secret in memory until it reloads, so its chunks get rejected in the meantime (cleanly rejected, not corrupted or misattributed — see the Capture tab's help for the full webhook-secret behavior). This is a real, if usually brief and low-volume, gap — worth knowing about if you rotate a secret you suspect leaked and want to understand why a few sessions might briefly fail right afterward.
- Editing privacy or advanced capture settings — the same caveat applies. If you need a setting change to apply to every visitor immediately, including ones with the page already open, there's no way to force that from a hosted-script model — only a full page reload picks up new config, on any site that caches a script at all.
- This isn't unusual — it's the same caching trade-off every hosted third-party script (Segment, Intercom, Google Analytics, and so on) makes, weighing "don't force a fresh fetch on every single page view" against "changes take a little while to fully propagate."
Related
- Monitors — how UI Monitor capture and matching work overall
- UI Monitor Client API — the Client API settings these caching rules apply to
- UI Monitor Privacy — the privacy rules these caching rules apply to