<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Caching on Vedant Andhale</title>
    <link>https://www.vedant.me/tags/caching/</link>
    <description>Recent content in Caching on Vedant Andhale</description>
    <image>
      <url>https://www.vedant.me/</url>
      <link>https://www.vedant.me/</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Thu, 10 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.vedant.me/tags/caching/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Before caching a result, define when it is wrong</title>
      <link>https://www.vedant.me/notebook/caching-is-a-correctness-problem/</link>
      <pubDate>Thu, 10 Sep 2026 00:00:00 +0000</pubDate>
      
      <guid>https://www.vedant.me/notebook/caching-is-a-correctness-problem/</guid>
      <description>Cache keys, stale data and invalidation are part of the result contract, not just performance settings.</description>
      <content:encoded><![CDATA[<p>A cached response can be fast and still belong to the wrong user, the wrong currency or an old version of the underlying data. The first caching question should be: when would reusing this value produce the wrong answer?</p>
<p>Imagine an endpoint that returns a price. A key containing only the product ID looks reasonable until the price also depends on currency, customer tier or region. Those inputs are part of the result even if they do not appear in the URL.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">cache_key</span> <span class="o">=</span> <span class="p">(</span><span class="n">product_id</span><span class="p">,</span> <span class="n">currency</span><span class="p">,</span> <span class="n">customer_tier</span><span class="p">,</span> <span class="n">pricing_version</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>This is an illustrative key, not a complete pricing design. Its purpose is to make the dependencies visible. If account-specific permissions affect the response, those boundaries also need to be reflected in the caching strategy.</p>
<h2 id="freshness-is-a-product-decision">Freshness is a product decision</h2>
<p>A five-minute-old avatar and a five-minute-old available balance carry different consequences. A time-to-live is meaningful only after someone decides what stale data is acceptable for that operation.</p>
<p>Expiry also does not solve every invalidation problem. An update followed immediately by a read can still return an old cached value. Options include invalidating on writes, versioning keys or accepting a documented delay. Each choice creates different failure modes.</p>
<h2 id="check-the-uncomfortable-cases">Check the uncomfortable cases</h2>
<p>Before measuring a hit rate, I would check that:</p>
<ul>
<li>Two users cannot receive each other&rsquo;s private result.</li>
<li>A change in an input that affects the result changes the cache lookup.</li>
<li>An update behaves as promised on the next read.</li>
<li>A cache outage has an intentional failure or fallback path.</li>
</ul>
<p>For HTTP caches, headers add another layer to this contract. <code>no-cache</code> permits storage but requires validation before reuse; <code>no-store</code> tells a cache not to store the response. They are not interchangeable ways to say “please be fresh.”</p>
<p>A cache is easier to operate when its correctness rule fits in a sentence. The performance measurements come after that rule is clear.</p>
<p>Reference: <a href="https://www.rfc-editor.org/rfc/rfc9111.html">HTTP caching specification, RFC 9111</a>.</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
