<?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 IT Comparison</title><link>https://comparison.metacog.co.kr/tags/caching/</link><description>Recent content in Caching on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 06 Sep 2026 09:45:20 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/caching/index.xml" rel="self" type="application/rss+xml"/><item><title>Cache Freshness vs Hit Rate: Correctness vs Efficiency</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-cache-freshness-vs-hit-rate-correctness-vs-efficiency/</link><pubDate>Sun, 06 Sep 2026 09:45:20 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-cache-freshness-vs-hit-rate-correctness-vs-efficiency/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Cache freshness measures whether the data returned by a cache still matches the current state of its source of truth, while hit rate measures how often requests are answered directly from the cache instead of falling through to the origin. The two metrics pull in opposite directions: optimizing for &lt;strong class="kw"&gt;freshness&lt;/strong&gt; means shorter TTLs and more origin traffic, while optimizing for &lt;strong class="kw"&gt;hit rate&lt;/strong&gt; means longer TTLs and a higher chance of serving stale data. Tuning a cache well means choosing the right balance point for that specific data&amp;rsquo;s tolerance for staleness.&lt;/p&gt;</description></item><item><title>Local vs Shared Cache: Per-Instance Memory vs Centralized Cache Service</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-local-vs-shared-cache-per-instance-memory-vs-centralized-cac/</link><pubDate>Sun, 06 Sep 2026 09:43:40 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-local-vs-shared-cache-per-instance-memory-vs-centralized-cac/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;A &lt;strong class="kw"&gt;local cache&lt;/strong&gt; stores data in the memory of a single application process, giving the fastest possible reads but no visibility into what other instances hold. A &lt;strong class="kw"&gt;shared cache&lt;/strong&gt; lives in a separate service that every instance queries over the network, trading a bit of latency for one consistent view of cached data across the whole fleet. The choice shapes how you handle invalidation, scaling, and failure in a multi-instance deployment.&lt;/p&gt;</description></item><item><title>CDN vs Origin Server: Who Actually Serves the Request</title><link>https://comparison.metacog.co.kr/posts/2026-08-03-cdn-vs-origin-server-who-actually-serves-the-request/</link><pubDate>Mon, 03 Aug 2026 06:23:28 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-03-cdn-vs-origin-server-who-actually-serves-the-request/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;A &lt;strong class="kw"&gt;CDN&lt;/strong&gt; is a distributed network of edge servers that caches and delivers content close to users, while the &lt;strong class="kw"&gt;origin server&lt;/strong&gt; is the single authoritative source where that content is created or stored. The distinction matters for latency, scalability, and resilience, since most requests should never need to reach the origin at all.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;circle cx="70" cy="200" r="24" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="70" y="205" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;Client&lt;/text&gt;&lt;rect x="150" y="70" width="200" height="220" rx="8" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="250" y="52" text-anchor="middle" style="fill:var(--primary)" font-size="16" font-weight="bold"&gt;CDN&lt;/text&gt;&lt;text x="250" y="90" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;Distributed edge locations&lt;/text&gt;&lt;circle cx="200" cy="140" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;circle cx="300" cy="140" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;circle cx="250" cy="200" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;circle cx="200" cy="250" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;circle cx="300" cy="250" r="16" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="250" y="278" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;Cache: static &amp;amp; edge-computed content&lt;/text&gt;&lt;rect x="460" y="150" width="140" height="90" rx="8" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="530" y="133" text-anchor="middle" style="fill:var(--primary)" font-size="16" font-weight="bold"&gt;Origin Server&lt;/text&gt;&lt;text x="530" y="192" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;Single source&lt;/text&gt;&lt;text x="530" y="207" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;of truth&lt;/text&gt;&lt;line x1="95" y1="190" x2="148" y2="165" style="stroke:var(--content)" stroke-width="1.5"/&gt;&lt;polygon points="148,165 139,163 143,171" style="fill:var(--content)"/&gt;&lt;text x="115" y="150" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;request&lt;/text&gt;&lt;line x1="148" y1="215" x2="95" y2="210" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;polygon points="95,210 104,206 104,215" style="fill:var(--compare-a)"/&gt;&lt;text x="118" y="235" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;cached response&lt;/text&gt;&lt;line x1="352" y1="180" x2="458" y2="185" style="stroke:var(--compare-b)" stroke-width="1.5" stroke-dasharray="5,4"/&gt;&lt;polygon points="458,185 449,181 450,190" style="fill:var(--compare-b)"/&gt;&lt;text x="405" y="165" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;on cache miss&lt;/text&gt;&lt;line x1="458" y1="215" x2="352" y2="210" style="stroke:var(--compare-b)" stroke-width="1.5" stroke-dasharray="5,4"/&gt;&lt;polygon points="352,210 361,206 361,215" style="fill:var(--compare-b)"/&gt;&lt;text x="405" y="233" text-anchor="middle" style="fill:var(--secondary)" font-size="9"&gt;origin pull &amp;amp; cache&lt;/text&gt;&lt;text x="320" y="330" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;Most requests resolve at the edge; only misses/dynamic content reach the origin&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;CDN&lt;/th&gt;
&lt;th&gt;Origin Server&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Role in request path&lt;/td&gt;
&lt;td&gt;Intercepts requests at the edge and serves cached content directly&lt;/td&gt;
&lt;td&gt;Authoritative backend that generates or stores the original content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geographic distribution&lt;/td&gt;
&lt;td&gt;Many points of presence worldwide, close to end users&lt;/td&gt;
&lt;td&gt;Typically one or a few fixed data center locations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content served&lt;/td&gt;
&lt;td&gt;Cached copies of static assets or cacheable API responses&lt;/td&gt;
&lt;td&gt;Dynamically generated pages or master copies of files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cache miss handling&lt;/td&gt;
&lt;td&gt;Forwards uncached requests to the origin and stores the response per TTL&lt;/td&gt;
&lt;td&gt;Processes every request that reaches it; has no caching layer of its own&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Latency&lt;/td&gt;
&lt;td&gt;Low, since content is served from the nearest edge node&lt;/td&gt;
&lt;td&gt;Higher, since every request travels to one fixed location&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Load on backend&lt;/td&gt;
&lt;td&gt;Absorbs most traffic, shielding the origin from direct load&lt;/td&gt;
&lt;td&gt;Only handles cache misses and non-cacheable requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resilience to outages&lt;/td&gt;
&lt;td&gt;Can keep serving stale cached content if the origin goes down&lt;/td&gt;
&lt;td&gt;Site is effectively unavailable for anything not already cached elsewhere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling and cost&lt;/td&gt;
&lt;td&gt;Scales via the CDN provider&amp;rsquo;s global network, billed per bandwidth/requests&lt;/td&gt;
&lt;td&gt;Must be scaled and provisioned directly, billed for compute and hosting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CDN content lives on distributed &lt;strong class="kw"&gt;edge nodes&lt;/strong&gt;; the origin server is the single &lt;strong class="kw"&gt;source of truth&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;CDN caching cuts &lt;strong class="kw"&gt;latency&lt;/strong&gt; for users, but every &lt;strong class="kw"&gt;cache miss&lt;/strong&gt; still lands on the origin.&lt;/li&gt;
&lt;li&gt;CDN edge caching gives resilience against &lt;strong class="kw"&gt;origin outages&lt;/strong&gt; by serving stale content.&lt;/li&gt;
&lt;li&gt;Origin servers own &lt;strong class="kw"&gt;dynamic content&lt;/strong&gt; generation; CDNs only store what&amp;rsquo;s actually &lt;strong class="kw"&gt;cacheable&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;CDN&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Cache-Aside vs Write-Through vs Write-Behind: Caching Strategies Compared</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-cache-aside-vs-write-through-vs-write-behind-caching-strateg/</link><pubDate>Sun, 02 Aug 2026 23:52:10 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-cache-aside-vs-write-through-vs-write-behind-caching-strateg/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Caching strategies differ mainly in who updates the cache and when. &lt;strong class="kw"&gt;Cache-Aside&lt;/strong&gt; leaves the application responsible for loading data into the cache on a miss and writing straight to the database, while &lt;strong class="kw"&gt;write-through/write-behind&lt;/strong&gt; caches push writes through the cache itself — synchronously for durability or asynchronously for speed. The choice shapes consistency guarantees, crash-safety, and how much write latency the app absorbs.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;defs&gt;&lt;marker id="arrowA" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"&gt;&lt;path d="M0,0 L10,5 L0,10 z" style="fill:var(--compare-a)"/&gt;&lt;/marker&gt;&lt;marker id="arrowB" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"&gt;&lt;path d="M0,0 L10,5 L0,10 z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;text x="16" y="28" font-size="15" font-weight="bold" style="fill:var(--primary)"&gt;Cache-Aside&lt;/text&gt;&lt;rect x="20" y="50" width="70" height="36" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="55" y="72" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;App&lt;/text&gt;&lt;rect x="285" y="50" width="80" height="36" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="325" y="72" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Cache&lt;/text&gt;&lt;rect x="545" y="50" width="70" height="36" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="580" y="72" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;DB&lt;/text&gt;&lt;line x1="95" y1="68" x2="280" y2="68" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;text x="185" y="60" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;read&lt;/text&gt;&lt;line x1="370" y1="68" x2="540" y2="68" stroke-dasharray="5,4" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)" marker-start="url(#arrowA)"/&gt;&lt;text x="455" y="95" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;on miss: fetch + populate&lt;/text&gt;&lt;line x1="10" y1="130" x2="630" y2="130" stroke-dasharray="4,4" style="stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="16" y="153" font-size="15" font-weight="bold" style="fill:var(--primary)"&gt;Write-Through&lt;/text&gt;&lt;rect x="20" y="168" width="70" height="36" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="55" y="190" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;App&lt;/text&gt;&lt;rect x="285" y="168" width="80" height="36" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="325" y="190" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Cache&lt;/text&gt;&lt;rect x="545" y="168" width="70" height="36" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="580" y="190" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;DB&lt;/text&gt;&lt;line x1="95" y1="186" x2="280" y2="186" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;text x="185" y="178" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;write&lt;/text&gt;&lt;line x1="370" y1="186" x2="540" y2="186" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;text x="455" y="178" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;sync write&lt;/text&gt;&lt;line x1="10" y1="248" x2="630" y2="248" stroke-dasharray="4,4" style="stroke:var(--border)" stroke-width="1"/&gt;&lt;text x="16" y="271" font-size="15" font-weight="bold" style="fill:var(--primary)"&gt;Write-Behind&lt;/text&gt;&lt;rect x="20" y="286" width="70" height="36" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="55" y="308" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;App&lt;/text&gt;&lt;rect x="285" y="286" width="80" height="36" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="325" y="308" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Cache&lt;/text&gt;&lt;rect x="545" y="286" width="70" height="36" rx="4" stroke-dasharray="4,3" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="580" y="308" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;DB&lt;/text&gt;&lt;line x1="95" y1="304" x2="280" y2="304" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;text x="185" y="296" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;write (fast ack)&lt;/text&gt;&lt;line x1="370" y1="304" x2="540" y2="304" stroke-dasharray="5,4" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;text x="455" y="296" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;async flush (delayed)&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Cache-Aside&lt;/th&gt;
&lt;th&gt;Write-Through / Write-Behind&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read path&lt;/td&gt;
&lt;td&gt;App checks the cache first; on a miss, it reads from the DB itself and populates the cache&lt;/td&gt;
&lt;td&gt;Cache is always kept current on writes, so reads simply hit the cache without app-managed fallback logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write path&lt;/td&gt;
&lt;td&gt;App writes directly to the DB; the cache entry is invalidated or left stale until the next read&lt;/td&gt;
&lt;td&gt;App writes only to the cache; the cache layer propagates the write to the DB itself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write latency perceived by app&lt;/td&gt;
&lt;td&gt;Only DB write latency, since the cache isn&amp;rsquo;t touched on write&lt;/td&gt;
&lt;td&gt;Write-Through waits for both cache and DB commit; Write-Behind returns after the cache write only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consistency between cache and DB&lt;/td&gt;
&lt;td&gt;Brief staleness window possible between invalidation and the next read&lt;/td&gt;
&lt;td&gt;Write-Through stays consistent immediately; Write-Behind lags until the queued flush completes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data loss risk on crash&lt;/td&gt;
&lt;td&gt;None — the DB is always the write target, so a cache crash loses nothing&lt;/td&gt;
&lt;td&gt;Write-Through has no loss; Write-Behind can lose unflushed writes if the cache crashes before flush&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation complexity&lt;/td&gt;
&lt;td&gt;App owns miss handling and invalidation logic explicitly&lt;/td&gt;
&lt;td&gt;Cache layer owns persistence logic; Write-Behind adds a queue/flush scheduler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use case&lt;/td&gt;
&lt;td&gt;Read-heavy workloads with unpredictable key access, e.g. Redis in front of a relational DB&lt;/td&gt;
&lt;td&gt;Write-Through suits systems needing instant durability; Write-Behind suits high write-throughput systems tolerant of brief loss, e.g. metrics buffers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Cache-Aside puts the application in charge of both fetch-on-miss and invalidation, while write-through/write-behind push that responsibility into the &lt;strong class="kw"&gt;cache layer&lt;/strong&gt; itself&lt;/li&gt;
&lt;li&gt;Only Write-Behind delivers real &lt;strong class="kw"&gt;write latency&lt;/strong&gt; savings by acknowledging before the DB commit completes&lt;/li&gt;
&lt;li&gt;Write-Through guarantees immediate durability at write time, while Write-Behind trades some of that &lt;strong class="kw"&gt;durability&lt;/strong&gt; for throughput&lt;/li&gt;
&lt;li&gt;Cache-Aside is the only strategy where a cache outage never risks &lt;strong class="kw"&gt;data loss&lt;/strong&gt;, since writes never pass through it&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Cache-Aside&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>