Skip to content
Search lessons, topics, tests…
Esc

    ↑ ↓ moveEnter openEsc close
    Cheat sheets: all cheat sheets

    Cache Keys, Tenant Boundaries, and Cache-Aside Reads

    Build cache keys around tenant and user boundaries.

    Tenant A’s price for product 42 is 80; tenant B’s is 100. A warms product:42, then B requests it. Predict B’s result and choose the smallest key boundary that preserves the price contract.

    Use this note for key dimensions and authorization placement. Use Concurrent Cache Misses for admission limits and Expiration and Invalidation Races for stale fills.

    Keep access separate from storage

    Caching is about saving work after you already know what data is allowed to be served. Authorization is about deciding whether the caller may see the data at all. Those are different responsibilities.

    A common interview trap is to blur them together: “If the item is missing from cache, deny access.” That is incorrect. A cache miss only means the cache does not currently hold a value. It says nothing about whether the user is allowed to load the value from the database or another source of truth.

    For a product catalog, a public product page might be safe to cache broadly, while a tenant-specific price, contract discount, or hidden inventory flag must be isolated. If two tenants can see different effective data, then the cache key must encode the boundary that changes the answer.

    Authorization nuance: consider a document-owner policy. The app needs the document owner before it can decide access. The authorization API accepts a resource and returns an authorization result; therefore this policy needs that resource first. Finish authorization before returning protected data. Microsoft: authorization API contract.

    Product-catalog path (authorization inputs already available):

    Text
    request
    -> authorize
    -> build safe cache key
    -> read cache
    -> if miss, load source
    -> store
    -> return

    For the illustrated path, authorization inputs are already available. A resource-based policy may instead require a resource lookup first. In either path, finish authorization before returning protected data, including a cache hit.

    Build keys from response differences

    Cache-aside means the application controls the read path explicitly. On a read request, the application first checks the cache. If the value is present, it returns the cached value. If the value is absent, the application loads the canonical data from the database or service, then populates the cache, then returns the data.

    For interviews, describe it this way: the application is responsible for keeping the cache warm on demand.

    The tricky part is designing the key. A good key reflects every dimension that can change the result. In a multi-tenant product catalog, that might include:

    • tenant ID, if product visibility or pricing differs by tenant
    • user role or entitlements, if the response depends on permissions
    • locale, if translated text is cached
    • currency or region, if prices are rendered differently
    • product ID or SKU, of course

    A bad key omits one of those dimensions. Then one caller can receive another caller’s cached response. That is a data leak, even if the underlying database access is properly protected.

    For example, suppose tenant A has a negotiated price of $80 and tenant B sees the standard price of $100. If the cache key is only product:42, the first tenant to request the product may populate the cache with the wrong price for the other tenant. The fix is not “add a permission check inside cache.” The fix is to make the key tenant-aware, such as tenant:A:product:42:price. If the user role also changes the answer, include it too.

    Keep in mind the difference between public and private data. Public product descriptions might be safe to share across tenants, so a broader key could be acceptable. Private data should be scoped tightly. The point is not to make every key as specific as possible; it is to make each key as specific as the data variance requires.

    In practice, use a stable key format and treat it as part of your API contract. That makes reasoning and invalidation easier. A common pattern is a namespaced prefix:

    Text
    catalog:v1:tenant:{tenantId}:product:{productId}

    The v1 portion helps when schema or shaping changes. If you change the payload structure, a versioned namespace lets you avoid mixing old and new shapes.

    For cache-aside, the application also owns the write path. The source of truth remains the database or service. After a product update, you might invalidate related keys or write through an updated value, depending on the design. But even then, the cache does not become the authority; it just mirrors data that the application has already decided is valid.

    Another useful interview distinction is between in-process and distributed caching. An in-process cache is local to one application instance, so it is fast but not shared. A distributed cache is shared across instances, which helps scale out, but it is still just a cache unless you explicitly build stronger coordination on top. Do not assume a distributed cache gives you locking, consensus, or correctness guarantees for writes.

    Failure modes

    Here are the most common mistakes interviewers expect you to catch:

    1. Using a too-generic key
    • Example: product:42
    • Risk: cross-tenant or cross-user leakage
    1. Putting authorization inside the cache lookup
    • Risk: a cache miss is not a deny decision
    • Correct approach: enforce the required policy before returning protected data; load authorization inputs first when the policy needs the resource
    1. Caching user-specific or tenant-specific data under a shared key
    • Risk: one caller receives another caller’s response
    1. Assuming the cache is the source of truth
    • Risk: stale or partial data becomes authoritative by accident
    1. Ignoring schema evolution
    • Risk: old cache entries collide with new response shapes
    1. Assuming distributed cache means distributed locking
    • Risk: concurrent writers or refreshers still race unless you add explicit coordination

    A good failure timeline to explain in an interview:

    Text
    T1: tenant A requests product 42 -> cache miss -> load price 80 -> store under product:42
    T2: tenant B requests product 42 -> cache hit -> receives price 80, but should see 100

    That timeline shows why the cache key, not just the cached value, must respect tenant boundaries.

    Check the policy boundary

    A document-owner policy needs the loaded document. The cache may contain it. Which ordering preserves the access check?

    A Authorize from the route ID alone, because a cached document has already been authorized.
    B Load the required resource, evaluate the current caller’s policy, then return it only on success.
    C Treat a cache miss as denial and a cache hit as permission.
    D Include the user ID in the key and omit policy evaluation on cache hits.
    Show answer

    Correct answer: B

    Resource-based authorization needs the resource as an input. Its storage source does not grant access. A scoped key prevents response collisions but does not replace current authorization.

    Hint: Separate obtaining policy inputs from returning protected data.

    Interview drill — answer before checking

    1. Why is cache-aside not an authorization mechanism?
    2. What should be part of a cache key in a multi-tenant product system?
    3. When is it acceptable to share a cache entry across tenants?
    4. Does a distributed cache automatically prevent race conditions?

    Check your answer

    1. Because authorization decides whether the caller may access data, while cache-aside only decides whether to load from cache or the source on a read. A cache miss may simply mean the data is cold. The application must still enforce access rules before returning any data.
    1. Any dimension that changes the returned value, such as tenant ID, product ID, locale, currency, or entitlement tier.
    1. Only when the cached response is truly identical and safe for all of them, such as a public product description with no tenant-specific shaping.
    1. No. A distributed cache shares storage, not necessarily coordination semantics. It can still need explicit locking, versioning, or invalidation design.

    TechInterviewNotes Editorial Team · Updated 28 Oct 2026 ·