What this usually means
In a multi-tenant application, every piece of cached data must be scoped to a tenant. If the cache key does not include a tenant identifier, the first tenant that populates the cache shares its data with every other tenant. This is a data leak, not just a stale data bug. It is especially dangerous because it can go unnoticed: the data looks valid, just belonging to the wrong tenant.
The first ten minutes \u2014 establish facts before touching code.
- 1Examine the cache key construction for every cache read and write. Does every key include a tenant identifier?
- 2Log the cache key used for requests from different tenants. Do they produce different keys?
- 3Check Redis or cache store directly. Do key names contain tenant IDs?
- 4Trace a request from Tenant A and Tenant B for the same resource. They should hit different cache keys.
- 5Audit all cache middleware, decorators, and helper functions. Do they have access to the tenant context?
The specific files, logs, configs, and dashboards that usually own this bug.
- searchCache key generation code — every function that builds a cache key
- searchCache middleware or decorators — how they derive the cache key from the request
- searchTenant context — is the tenant ID reliably available when cache keys are built?
- searchRedis or cache dashboard — inspect actual keys to verify tenant prefix
- searchMulti-tenant request routing — is the tenant resolved before or after cache operations?
- searchAll cache invalidation code — does it also include tenant scope?
Practical causes, not theory. These are the things you will actually find.
- warningCache key omits the tenant ID entirely
- warningCache key uses a tenant name instead of a tenant ID and names collide
- warningCache key is built before tenant identification middleware runs
- warningA shared cache instance is used without tenant namespacing
- warningCache invalidation does not include tenant scope, so one tenant's invalidation affects all tenants
- warningA library or framework cache layer does not know about tenancy and uses request URL alone
Concrete fix directions. Pick the one that matches your root cause.
- buildPrefix every cache key with the tenant ID: `tenant:{tenantId}:resource:{resourceId}`
- buildBuild cache keys through a single function that enforces tenant scope
- buildEnsure tenant resolution happens before any cache operations in the request lifecycle
- buildAdd integration tests that verify two different tenants get different cached data
- buildAudit all cache interactions in the codebase for tenant scope compliance
- buildUse separate cache instances or databases per tenant if isolation is critical
A fix you cannot prove is a guess. Close the loop.
- verifiedMake the same request as Tenant A and Tenant B. The responses must differ and be correct for each.
- verifiedCheck Redis: two different keys should exist, one per tenant.
- verifiedClear Tenant A's cache. Tenant B's cached data must not be affected.
- verifiedRun a test that caches Tenant A's data, makes a request as Tenant B, and verifies no cross-tenant data.
- verifiedAudit every cache key construction site in the codebase for tenant prefix.
Things that make this bug worse or harder to find.
- warningAssuming a shared cache is safe without tenant namespacing
- warningNot testing cache isolation across tenants in multi-tenant applications
- warningUsing the request path as the sole cache key without tenant context
- warningNot auditing cache invalidation for tenant scope
- warningTreating a tenant cache leak as a performance bug instead of a data leak