Cache Implementation
Exact caching reuses a stored result only when the exact same item is requested, so the lookup key must match precisely.
The Cost of Answering the Same Request Twice
Imagine an AI application that receives the same kind of question many times a minute. Each time, it may call a model, run a multi-step reasoning process, search a vector index, or query a database. Some of these actions are slow, and some cost money to run. If the application has already produced an answer for a request, running the whole process again is wasted effort. Exact caching avoids that waste by keeping a record of past results and reusing them when the same request comes back.
This article follows one question from start to finish: when the system receives a request, how does it decide whether a stored result can be used, and what has to be true before that reuse is safe? The answer depends on the word exact, so we start there.
What do you think happens?
A cache already holds a stored summary for the product 'Alpha'. A new request asks for a summary of 'Alpha Pro', a product whose name sounds nearly identical. Does the cache return the stored Alpha summary?
Reveal answer
No. The request is a miss, and the system has to create a summary for Alpha Pro.
Exact caching reuses a stored result only when the exact same item is requested. A summary of one product cannot be handed back for a different product, even when the two sound alike. The lookup key is the request itself, so only an identical key produces a hit.
Watching the Cache Change Over Requests
The source describes a concrete case: a user asks a model to summarize a product. Before doing any work, the system checks whether a summary of this exact product already exists. If it does, the stored summary is fetched, which is a hit. If it does not, the system creates the summary and stores it for next time, which is a miss. The best way to understand this logic is to watch the contents of the cache change across a short run of requests.
Tracing hits and misses in a product-summary cache
The cache starts empty. Five summary requests arrive in this order: Alpha, Beta, Alpha, Alpha Pro, Beta. For each request, determine whether it is a hit or a miss, and state what the cache holds afterward.
- 1Request 1: Alpha
The cache is empty, so no key matches. This is a miss. The system creates the Alpha summary and stores it under the key Alpha. Cache holds: Alpha.
- 2Request 2: Beta
The key Beta is not in the cache. This is a miss. The Beta summary is created and stored. Cache holds: Alpha, Beta.
- 3Request 3: Alpha
The key Alpha matches a stored entry exactly. This is a hit, so the stored Alpha summary is fetched and no new work is done. The cache does not change: Alpha, Beta.
- 4Request 4: Alpha Pro
Alpha Pro is a different product from Alpha, so the exact key is not present. This is a miss even though the name looks similar. Cache holds: Alpha, Beta, Alpha Pro.
- 5Request 5: Beta
The key Beta is stored, so this is a hit. The stored Beta summary is returned. Cache still holds: Alpha, Beta, Alpha Pro.
Requests 3 and 5 are hits, and requests 1, 2, and 4 are misses. Only the misses did new work, and each miss added one entry. Hits reused existing entries without changing the cache.
Every miss adds an entry to the cache, and every hit leaves the cache unchanged. The cache grows only through misses, which is why the question of how big it may become matters later in this article.
Why the Match Has to Be Exact
Exact caching reuses a stored result only when the exact same item is requested, so the lookup key must match precisely. The lookup key is the request itself, and only an identical key produces a hit.
Read the diagram as a lookup table. The request Alpha finds its stored value because the key matches exactly. The request Alpha Pro Max looks close to the stored key Alpha Pro, but it is not identical, so the cache does not return that entry. A near match is still a miss, because exact caching never reuses a result for a request that is merely similar.
The same pattern appears in embedding-based retrieval, which the source also names as a use of exact caching. When an incoming query is already in the vector search cache, the stored result is fetched. If it is not, a vector search runs for that query and its result is cached. In both cases the purpose is to avoid redundant work: repeating a search that has already been done for the same query.
Exact caching is most appealing for certain requests. The source highlights queries that involve multiple steps, such as chain-of-thought reasoning, and time-consuming actions such as retrieval, SQL execution, or web search. The more work a request requires, the more there is to save by reusing its answer.
Choosing Where the Cache Lives
An exact cache can be implemented with in-memory storage, which allows fast retrieval. The source notes a limit to this choice: in-memory storage is restricted in how much it can hold. Because of that limit, a cache can instead be built on a database such as PostgreSQL or Redis, or on tiered storage, which is used to balance speed against storage capacity.
| Storage option | What it offers | What it gives up |
|---|---|---|
| In-memory storage | Fast retrieval of stored results | Restricted in how much it can hold |
| Database such as PostgreSQL or Redis | A larger home for cached results when in-memory space runs short | Reads are less fast than in-memory retrieval, since faster storage tends to hold less and larger storage tends to be slower to read |
| Tiered storage | A balance between speed and storage capacity | Requires a design decision about where results should live along the speed-capacity spectrum |
Storage options for an exact cache, as described in the source
Reading this as a tradeoff helps. Faster storage tends to hold less, and larger storage tends to be slower to read. The cache design is a decision about where on that spectrum your results should live, given the volume of requests your application handles. A small volume of requests may fit comfortably in fast memory, while a high volume may push the design toward larger storage.
When the Cache Is Full
A cache that only ever grows will eventually cause a problem, especially when storage is limited. The source states that having an eviction policy is crucial for managing cache size and maintaining performance. An eviction policy is the rule the system uses to decide which entries to remove when space is needed.
The source names three common eviction policies. Least Recently Used (LRU) is one. Least Frequently Used (LFU) is another. First in, first out (FIFO) is the third. The names indicate what each policy looks at: LRU is concerned with how recently an entry was used, LFU with how often it was used, and FIFO with the order in which entries arrived. The source lists these names without describing their internal mechanics, so treat the names and what they track as the core facts to remember.
| Policy | What it looks at | Entry it is concerned with removing when space is needed |
|---|---|---|
| LRU (Least Recently Used) | How recently an entry was used | The entry that has gone longest without being used |
| LFU (Least Frequently Used) | How often an entry was used | The entry that has been used the fewest times |
| FIFO (First In, First Out) | The order in which entries arrived | The entry that arrived earliest |
Common eviction policies named in the source, with the concern implied by each name
The three policies answer the same question, which entry to remove, but they answer it from different evidence: recency of use, frequency of use, or arrival order.
Requests That Should Bypass the Cache
Not every request is worth storing. The source says how long a query should stay in the cache depends on how likely that query is to be called again. Two categories are called out as poor candidates. The first is user-specific queries, such as a question about the status of one's recent order. That result is unlikely to be reused by other users, so it should not be cached. The second is time-sensitive queries, such as asking about the weather. A stored answer to a question whose correct answer changes over time becomes misleading, so caching it makes less sense.
The flowchart turns the source's guidance into a sequence of questions. The first two questions screen out requests that are user-specific or time-sensitive. The third asks whether the request is likely to be called again, which the source describes as the factor that governs how long a query should stay in the cache. Only requests that pass all three checks reach the exact-key lookup. The source also notes that many teams train a classifier to predict whether a query should be cached. The source does not describe how such a classifier is built, so the important idea is the goal it serves: predicting the likelihood that a query will be reused.
Caching has a hazard beyond wasted storage. The source warns that caching, when not properly handled, can cause data leaks. Consider an ecommerce site where a user asks, 'What is the return policy for electronics products?' The question sounds the same for everyone, but in this case the return policy depends on the user's membership. To answer, the system first retrieves that user's information, then generates a response that contains it. If that response were cached under the generic question and then returned to a different user with the same question, the second user would receive an answer built from someone else's membership details.
Common Mistakes With Exact Caching
Common mistake Treating a near match as a hit
What it looks likeA request for Alpha Pro Max is served the stored Alpha Pro summary because the names are almost the same.
Why it failsExact caching reuses a stored result only when the exact same item is requested. A near match has a different lookup key.
Do this insteadCompare keys exactly. Only an identical key produces a hit; anything else is a miss.
Common mistake Caching every request by default
What it looks likeWeather questions and personal order-status questions are stored like any other query.
Why it failsUser-specific results are unlikely to be reused by others, and time-sensitive answers become misleading as the correct answer changes.
Do this insteadScreen requests first, bypassing the cache for user-specific or time-sensitive queries and for requests unlikely to be reused.
Common mistake Letting the cache grow without limit
What it looks likeEvery miss adds an entry, and no entry is ever removed.
Why it failsThe source states that an eviction policy is crucial for managing cache size and maintaining performance.
Do this insteadChoose an eviction policy such as LRU, LFU, or FIFO to decide which entries to remove when space is needed.
Common mistake Assuming a generic-looking question has a generic answer
What it looks likeThe return policy question is cached, and the membership-dependent answer is then served to other users.
Why it failsThe source warns that improper caching can leak data when the answer depends on who is asking.
Do this insteadIdentify whether the response was built from user information before storing it.
Common mistake Choosing in-memory storage without considering its capacity limit
Trace It Yourself
The cache starts empty. The following summary requests arrive in order: Gamma, Delta, Gamma, Gamma Plus, Delta, Gamma. For each request, state whether it is a hit or a miss, and list the keys the cache holds after the request. Then explain why the Gamma Plus request does not reuse the stored Gamma summary.
Hints
- Start with an empty cache. The first time any key appears, the result must be a miss.
- A hit leaves the cache unchanged, while a miss adds one new key.
- Ask whether the key is identical to a stored key, not whether it sounds similar.
Key Takeaways
- Exact caching reuses a stored result only when the exact same item is requested, so the lookup key must match precisely; similar-looking requests are misses.
- Tracing a cache means applying one rule per request: a matching key is a hit and leaves the cache unchanged, while a miss does new work and adds an entry.
- An exact cache can live in in-memory storage for speed, in a database such as PostgreSQL or Redis, or in tiered storage; each choice trades speed against capacity.
- An eviction policy such as LRU, LFU, or FIFO decides which entry to remove when space is needed, based on recency of use, frequency of use, or arrival order.
- User-specific and time-sensitive queries are poor candidates for caching, and careless caching of answers that depend on the asker can leak private information.