Why Every Cache Key Includes the Customer
A cache is a short-term memory for software. Instead of rebuilding a website's menu, settings or sitemap on every visit, the application stores the finished answer under a name, called a key, and reuses it until something changes. Caching is one of the simplest ways to make a platform fast.
In a platform that serves many customers, caching also carries a hidden risk. If two customers' answers are stored under the same key, the second visitor gets the first customer's answer. That might be a harmless menu. It might be a list of members.
How a cache leak happens
Imagine a function that builds a website's header menu and caches it under the key "header_menu." The first visitor to any site builds the menu for their site and stores it. The next visitor, on a completely different customer's site, asks for "header_menu" and receives the first site's links.
Nothing crashed. No error was logged. A customer simply saw another organization's navigation. With settings, prices or private lists, the consequences are far worse.
Our naming rule
Every cache key in our platform that holds customer-specific data includes the customer's account identifier, and usually the specific website within that account. A menu is cached as something like "menu, account 49, site 44, header." Search settings, theme settings, sitemaps and page content all follow the same pattern.
When code may run outside any customer account, such as on our public marketing site, the key uses a clear placeholder for "no account" rather than leaving the slot empty. An empty slot is how two contexts accidentally share one key.
Host names belong in some keys too
Some answers depend not just on the account but on the address the visitor used. A website can be reached through its platform address and, later, through its own domain. Files such as robots.txt and llms.txt include full addresses, so their cache keys include the host as well. That way a visitor on the custom domain never receives a file that lists the old platform address.
Clearing the right things
Naming keys carefully also makes clearing them precise. When a customer saves their menus, we clear that customer's menu keys and nothing else. When a release changes how a sitemap is built, the release clears sitemap keys for every account. Because keys carry their owner, we can be specific about whose cache changes.
Where our cache supports tags, we group related keys so a whole family, such as all blog post content, can be refreshed together. The owner is still part of every individual key.
Caches that must survive a release
Not every cache is disposable. A few pieces of short-lived state, such as a lock that prevents two people from running the same long operation at once, need to survive the cache clear that happens on every release. Those live in a separate store that releases do not wipe. Choosing the right store for each kind of memory is part of the design.
Review questions we ask
When reviewing code that caches anything, we ask:
- Does the key include the account, and the website where relevant?
- Could this code run without an account, and what does the key look like then?
- Does the answer depend on the visitor's host or language?
- When the data changes, which keys must be cleared, and does the code clear them?
These questions take a minute and prevent one of the quietest kinds of data leak. They are part of the broader habit we call tenant-first thinking, which shapes everything in VoVo.
Frequently asked questions
What is a cache key?
A cache key is the name under which a stored answer is saved and later looked up. If two different answers share a key, one will overwrite or be confused with the other.
Can caching cause data leaks?
Yes. In a shared platform, a cache key that does not include the customer can serve one customer's data to another. Including the account in every key prevents this.
Why include the website address in some cache keys?
Some responses contain full addresses. If a site is reachable at two addresses, the cached response must match the address the visitor used.
Comments (0)
No comments yet. Be the first to share your thoughts!