<?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>Scalability on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/scalability/</link><description>Recent content in Scalability on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 06 Sep 2026 09:51:46 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/scalability/index.xml" rel="self" type="application/rss+xml"/><item><title>Stateful vs Stateless: Where the Session Lives</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-stateful-vs-stateless-where-the-session-lives/</link><pubDate>Sun, 06 Sep 2026 09:51:46 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-stateful-vs-stateless-where-the-session-lives/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;This comparison covers whether a server or protocol retains &lt;strong class="kw"&gt;session state&lt;/strong&gt; between requests, or treats every request as a fully &lt;strong class="kw"&gt;self-contained&lt;/strong&gt; unit with no memory of prior ones. The choice determines how you scale, fail over, and route traffic across instances.&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;text x="160" y="32" text-anchor="middle" font-size="16" style="fill:var(--primary)"&gt;Stateful&lt;/text&gt;&lt;text x="480" y="32" text-anchor="middle" font-size="16" style="fill:var(--primary)"&gt;Stateless&lt;/text&gt;&lt;rect x="40" y="60" width="110" height="50" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="95" y="90" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;Client&lt;/text&gt;&lt;path d="M150 85 L230 85" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;rect x="230" y="60" width="120" height="50" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="290" y="84" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Server A&lt;/text&gt;&lt;text x="290" y="100" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;session: id=42&lt;/text&gt;&lt;path d="M290 110 L290 150" style="stroke:var(--border)" stroke-width="1.5" stroke-dasharray="4,3" marker-end="url(#arrowN)"/&gt;&lt;text x="330" y="135" font-size="10" style="fill:var(--secondary)"&gt;must return&lt;/text&gt;&lt;text x="330" y="148" font-size="10" style="fill:var(--secondary)"&gt;to same server&lt;/text&gt;&lt;rect x="230" y="160" width="120" height="50" rx="6" style="fill:none;stroke:var(--border)" stroke-width="1.5" stroke-dasharray="4,3"/&gt;&lt;text x="290" y="189" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;Server B&lt;/text&gt;&lt;text x="290" y="204" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;no session data&lt;/text&gt;&lt;path d="M95 110 L95 200 L230 200" style="stroke:var(--compare-a)" stroke-width="1.5" fill="none" marker-end="url(#arrowA)"/&gt;&lt;line x1="20" y1="260" x2="620" y2="260" style="stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="360" y="60" width="110" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="415" y="90" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;Client&lt;/text&gt;&lt;text x="415" y="106" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;carries token&lt;/text&gt;&lt;path d="M470 85 L540 85" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;rect x="540 " y="60" width="70" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="575" y="90" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Server&lt;/text&gt;&lt;path d="M470 85 L540 160" style="stroke:var(--compare-b)" stroke-width="1.5" fill="none" marker-end="url(#arrowB)"/&gt;&lt;rect x="540" y="150" width="70" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="575" y="180" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Server&lt;/text&gt;&lt;text x="415" y="200" font-size="10" style="fill:var(--secondary)"&gt;any server can&lt;/text&gt;&lt;text x="415" y="213" font-size="10" style="fill:var(--secondary)"&gt;handle the request&lt;/text&gt;&lt;text x="320" y="300" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Stateful: server pins session context and routing depends on it&lt;/text&gt;&lt;text x="320" y="325" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Stateless: request carries all context, any node can serve it&lt;/text&gt;&lt;defs&gt;&lt;marker id="arrowA" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 z" style="fill:var(--compare-a)"/&gt;&lt;/marker&gt;&lt;marker id="arrowB" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;marker id="arrowN" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 z" style="fill:var(--border)"/&gt;&lt;/marker&gt;&lt;/defs&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;Stateful&lt;/th&gt;
&lt;th&gt;Stateless&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Request context&lt;/td&gt;
&lt;td&gt;Server retains prior interaction data across requests&lt;/td&gt;
&lt;td&gt;Each request carries all context needed to process it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session storage&lt;/td&gt;
&lt;td&gt;Held in server memory or local session store&lt;/td&gt;
&lt;td&gt;None on server; state lives in client token or database&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Routing requirement&lt;/td&gt;
&lt;td&gt;Requests must reach the same server (sticky sessions)&lt;/td&gt;
&lt;td&gt;Any server instance can handle any request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling model&lt;/td&gt;
&lt;td&gt;Vertical or sticky-session horizontal scaling only&lt;/td&gt;
&lt;td&gt;Trivial horizontal scaling, load balance freely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure recovery&lt;/td&gt;
&lt;td&gt;Server crash loses in-memory session unless replicated&lt;/td&gt;
&lt;td&gt;Server crash has no session impact, retry hits any node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client design&lt;/td&gt;
&lt;td&gt;Client can be thin, server tracks progress&lt;/td&gt;
&lt;td&gt;Client or token must resend full context each call&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical examples&lt;/td&gt;
&lt;td&gt;Database connections, WebSocket sessions, FTP&lt;/td&gt;
&lt;td&gt;REST APIs, HTTP with JWT, DNS lookups&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;Stateful servers keep &lt;strong class="kw"&gt;session memory&lt;/strong&gt;; stateless servers keep none between calls&lt;/li&gt;
&lt;li&gt;Stateless systems need &lt;strong class="kw"&gt;no sticky routing&lt;/strong&gt;, simplifying load balancers&lt;/li&gt;
&lt;li&gt;Stateful failover requires &lt;strong class="kw"&gt;session replication&lt;/strong&gt; to avoid data loss&lt;/li&gt;
&lt;li&gt;Stateless designs push state into the &lt;strong class="kw"&gt;client or token&lt;/strong&gt; instead of the server&lt;/li&gt;
&lt;li&gt;Horizontal scaling is &lt;strong class="kw"&gt;near-free&lt;/strong&gt; for stateless architectures&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;Stateful&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Replication vs Sharding: Copying Data vs Splitting Data</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-replication-vs-sharding-copying-data-vs-splitting-data/</link><pubDate>Sun, 06 Sep 2026 09:39:10 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-replication-vs-sharding-copying-data-vs-splitting-data/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Both are techniques for scaling a database beyond a single node, but they solve different problems: &lt;strong class="kw"&gt;replication&lt;/strong&gt; copies the entire dataset onto multiple nodes to boost availability and read capacity, while &lt;strong class="kw"&gt;sharding&lt;/strong&gt; splits the dataset into disjoint partitions across nodes to boost storage and write capacity. Large-scale systems typically use both together — sharding for horizontal scale, replication within each shard for durability.&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;line x1="320" y1="20" x2="320" y2="340" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4,4"/&gt;
&lt;text x="160" y="28" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="bold"&gt;Replication&lt;/text&gt;
&lt;text x="480" y="28" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="bold"&gt;Sharding&lt;/text&gt;
&lt;rect x="100" y="50" width="120" height="50" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;
&lt;text x="160" y="72" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Primary&lt;/text&gt;
&lt;text x="160" y="88" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;A B C D&lt;/text&gt;
&lt;line x1="140" y1="100" x2="105" y2="172" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;
&lt;line x1="180" y1="100" x2="225" y2="172" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;
&lt;rect x="50" y="175" width="110" height="55" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;
&lt;text x="105" y="197" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;Replica A&lt;/text&gt;
&lt;text x="105" y="213" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;A B C D&lt;/text&gt;
&lt;rect x="170" y="175" width="110" height="55" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;
&lt;text x="225" y="197" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;Replica B&lt;/text&gt;
&lt;text x="225" y="213" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;A B C D&lt;/text&gt;
&lt;text x="160" y="255" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;full dataset, copied&lt;/text&gt;
&lt;text x="160" y="272" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;to every node&lt;/text&gt;
&lt;rect x="420" y="50" width="120" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;text x="480" y="72" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Router&lt;/text&gt;
&lt;text x="480" y="88" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;key lookup&lt;/text&gt;
&lt;line x1="460" y1="100" x2="430" y2="172" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;line x1="500" y1="100" x2="550" y2="172" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;rect x="375" y="175" width="110" height="55" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;text x="430" y="197" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;Shard 1&lt;/text&gt;
&lt;text x="430" y="213" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;keys A-M&lt;/text&gt;
&lt;rect x="495" y="175" width="110" height="55" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;
&lt;text x="550" y="197" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;Shard 2&lt;/text&gt;
&lt;text x="550" y="213" text-anchor="middle" style="fill:var(--secondary)" font-size="10"&gt;keys N-Z&lt;/text&gt;
&lt;text x="480" y="255" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;dataset split into&lt;/text&gt;
&lt;text x="480" y="272" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;disjoint subsets&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;Replication&lt;/th&gt;
&lt;th&gt;Sharding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Primary goal&lt;/td&gt;
&lt;td&gt;Increase availability and read capacity&lt;/td&gt;
&lt;td&gt;Increase storage and write capacity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data distribution&lt;/td&gt;
&lt;td&gt;Full dataset copied to every node&lt;/td&gt;
&lt;td&gt;Dataset split into disjoint partitions across nodes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write path&lt;/td&gt;
&lt;td&gt;Writes go to primary, then propagate to replicas&lt;/td&gt;
&lt;td&gt;Writes routed to the single shard owning the key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read path&lt;/td&gt;
&lt;td&gt;Any replica (or primary) can serve any read&lt;/td&gt;
&lt;td&gt;Read must be routed to the shard holding the key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node failure impact&lt;/td&gt;
&lt;td&gt;Data survives since other copies exist&lt;/td&gt;
&lt;td&gt;That shard&amp;rsquo;s data becomes unavailable unless also replicated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consistency concern&lt;/td&gt;
&lt;td&gt;Replication lag between primary and replicas&lt;/td&gt;
&lt;td&gt;Cross-shard transactions and joins are hard to coordinate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling ceiling&lt;/td&gt;
&lt;td&gt;Bounded by primary&amp;rsquo;s write throughput&lt;/td&gt;
&lt;td&gt;Bounded by cross-shard coordination and key hotspots&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational overhead&lt;/td&gt;
&lt;td&gt;Failover and leader election&lt;/td&gt;
&lt;td&gt;Shard key design, rebalancing, and resharding&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;Replication duplicates the same data everywhere; sharding partitions it so each node holds only a slice&lt;/li&gt;
&lt;li&gt;Replication scales &lt;strong class="kw"&gt;reads&lt;/strong&gt; and durability; sharding scales &lt;strong class="kw"&gt;writes&lt;/strong&gt; and total storage&lt;/li&gt;
&lt;li&gt;Sharding introduces a routing layer that must know which shard owns a given key&lt;/li&gt;
&lt;li&gt;Losing a replica is harmless, but losing an unreplicated shard causes real &lt;strong class="kw"&gt;data loss&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Production systems commonly combine both: shard for scale, replicate each shard for resilience&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;Replication&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Vertical vs Horizontal Scaling: Bigger Box vs More Boxes</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-vertical-vs-horizontal-scaling-bigger-box-vs-more-boxes/</link><pubDate>Sun, 06 Sep 2026 09:36:59 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-vertical-vs-horizontal-scaling-bigger-box-vs-more-boxes/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Vertical scaling grows capacity by adding more &lt;strong class="kw"&gt;CPU/RAM&lt;/strong&gt; to a single machine, while horizontal scaling grows capacity by adding &lt;strong class="kw"&gt;more nodes&lt;/strong&gt; behind a load balancer. The choice shapes your application&amp;rsquo;s architecture, failure model, and cost curve as it grows.&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;text x="160" y="40" text-anchor="middle" font-size="18" style="fill:var(--primary)"&gt;Vertical&lt;/text&gt;&lt;text x="480" y="40" text-anchor="middle" font-size="18" style="fill:var(--primary)"&gt;Horizontal&lt;/text&gt;&lt;line x1="320" y1="20" x2="320" y2="340" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4 4"/&gt;&lt;rect x="120" y="230" width="80" height="60" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="265" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Server&lt;/text&gt;&lt;rect x="110" y="150" width="100" height="70" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="2"/&gt;&lt;text x="160" y="180" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Server&lt;/text&gt;&lt;text x="160" y="197" text-anchor="middle" font-size="11" style="fill:var(--secondary)"&gt;+CPU +RAM&lt;/text&gt;&lt;rect x="95" y="60" width="130" height="80" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="2.5"/&gt;&lt;text x="160" y="95" text-anchor="middle" font-size="13" style="fill:var(--content)"&gt;Server&lt;/text&gt;&lt;text x="160" y="114" text-anchor="middle" font-size="11" style="fill:var(--secondary)"&gt;++CPU ++RAM&lt;/text&gt;&lt;path d="M160 145 L160 232" style="stroke:var(--compare-a)" stroke-width="1.5" stroke-dasharray="3 3" fill="none"/&gt;&lt;path d="M155 60 L155 -0" style="stroke:var(--border)" stroke-width="0"/&gt;&lt;line x1="160" y1="40" x2="160" y2="58" style="stroke:var(--compare-a)" stroke-width="1.5" stroke-dasharray="3 3"/&gt;&lt;rect x="430" y="60" width="100" height="36" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="2"/&gt;&lt;text x="480" y="83" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Load Balancer&lt;/text&gt;&lt;line x1="480" y1="96" x2="400" y2="150" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="480" y1="96" x2="480" y2="150" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;line x1="480" y1="96" x2="560" y2="150" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;rect x="365" y="150" width="70" height="50" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="400" y="180" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Node&lt;/text&gt;&lt;rect x="445" y="150" width="70" height="50" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="180" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Node&lt;/text&gt;&lt;rect x="525" y="150" width="70" height="50" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="560" y="180" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Node&lt;/text&gt;&lt;rect x="485" y="230" width="70" height="50" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5" stroke-dasharray="4 4"/&gt;&lt;text x="520" y="260" text-anchor="middle" font-size="11" style="fill:var(--secondary)"&gt;+Node&lt;/text&gt;&lt;line x1="480" y1="200" x2="520" y2="228" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="3 3"/&gt;&lt;text x="160" y="330" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;Single node, growing&lt;/text&gt;&lt;text x="480" y="330" text-anchor="middle" font-size="12" style="fill:var(--secondary)"&gt;Many nodes, distributed&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;Vertical Scaling&lt;/th&gt;
&lt;th&gt;Horizontal Scaling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scaling mechanism&lt;/td&gt;
&lt;td&gt;Add CPU, RAM, or faster disks to one machine&lt;/td&gt;
&lt;td&gt;Add more machines/nodes to a shared pool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Architecture requirement&lt;/td&gt;
&lt;td&gt;Works with any app, no code changes needed&lt;/td&gt;
&lt;td&gt;Requires stateless design, load balancing, and shared state (session store, distributed cache)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upper limit&lt;/td&gt;
&lt;td&gt;Capped by the largest hardware SKU available&lt;/td&gt;
&lt;td&gt;Effectively unbounded, limited only by orchestration and cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Downtime during scale-up&lt;/td&gt;
&lt;td&gt;Often requires reboot or migration to bigger instance&lt;/td&gt;
&lt;td&gt;New nodes join the pool live, no downtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fault tolerance&lt;/td&gt;
&lt;td&gt;Single point of failure — one box, one crash&lt;/td&gt;
&lt;td&gt;Node failures are absorbed by the remaining pool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost curve&lt;/td&gt;
&lt;td&gt;Price rises non-linearly at the high end (diminishing returns)&lt;/td&gt;
&lt;td&gt;Roughly linear cost per added unit of capacity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational complexity&lt;/td&gt;
&lt;td&gt;Low — one server to patch, monitor, and secure&lt;/td&gt;
&lt;td&gt;Higher — needs service discovery, distributed monitoring, data consistency handling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use case&lt;/td&gt;
&lt;td&gt;Monolithic apps, relational databases, legacy systems&lt;/td&gt;
&lt;td&gt;Stateless web services, microservices, cloud-native workloads&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;Vertical scaling upgrades a &lt;strong class="kw"&gt;single machine&lt;/strong&gt;; horizontal scaling adds &lt;strong class="kw"&gt;more machines&lt;/strong&gt; to a pool&lt;/li&gt;
&lt;li&gt;Horizontal scaling demands &lt;strong class="kw"&gt;stateless services&lt;/strong&gt;, while vertical scaling needs no architectural change&lt;/li&gt;
&lt;li&gt;Vertical scaling has a hard &lt;strong class="kw"&gt;hardware ceiling&lt;/strong&gt;; horizontal scaling scales near-linearly&lt;/li&gt;
&lt;li&gt;A single oversized server is a &lt;strong class="kw"&gt;single point of failure&lt;/strong&gt;, unlike a distributed node pool&lt;/li&gt;
&lt;li&gt;Horizontal scaling trades simplicity for &lt;strong class="kw"&gt;operational complexity&lt;/strong&gt; in orchestration and consistency&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;Vertical Scaling&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Stateless vs Stateful Architecture: Where Request Context Lives</title><link>https://comparison.metacog.co.kr/posts/2026-08-04-stateless-vs-stateful-architecture-where-request-context-liv/</link><pubDate>Tue, 04 Aug 2026 05:18:18 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-04-stateless-vs-stateful-architecture-where-request-context-liv/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;This comparison covers how servers handle client context across requests: a &lt;strong class="kw"&gt;stateless&lt;/strong&gt; server treats every request as self-contained with no memory of what came before, while a &lt;strong class="kw"&gt;stateful&lt;/strong&gt; server keeps track of session data tied to a specific client across multiple requests. The choice shapes how easily a system scales, recovers from failure, and routes traffic under load.&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" font-family="sans-serif"&gt;&lt;line x1="320" y1="20" x2="320" y2="340" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4 4"/&gt;&lt;text x="160" y="35" text-anchor="middle" font-size="16" font-weight="bold" style="fill:var(--primary)"&gt;Stateless&lt;/text&gt;&lt;text x="480" y="35" text-anchor="middle" font-size="16" font-weight="bold" style="fill:var(--primary)"&gt;Stateful&lt;/text&gt;&lt;rect x="20" y="150" width="70" height="40" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="55" y="174" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Client&lt;/text&gt;&lt;rect x="130" y="150" width="70" height="40" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="165" y="168" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Load&lt;/text&gt;&lt;text x="165" y="182" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Balancer&lt;/text&gt;&lt;rect x="240" y="95" width="65" height="35" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="272" y="117" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Server A&lt;/text&gt;&lt;rect x="240" y="152" width="65" height="35" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="272" y="174" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Server B&lt;/text&gt;&lt;rect x="240" y="209" width="65" height="35" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="272" y="231" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Server C&lt;/text&gt;&lt;line x1="90" y1="170" x2="128" y2="170" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;line x1="200" y1="165" x2="238" y2="130" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;line x1="200" y1="170" x2="238" y2="170" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;line x1="200" y1="175" x2="238" y2="212" style="stroke:var(--compare-a)" stroke-width="1.5" marker-end="url(#arrowA)"/&gt;&lt;text x="160" y="280" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;any server can handle any request&lt;/text&gt;&lt;text x="160" y="296" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;no session stored server-side&lt;/text&gt;&lt;rect x="355" y="150" width="70" height="40" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="390" y="174" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Client&lt;/text&gt;&lt;rect x="470" y="140" width="90" height="60" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="515" y="165" text-anchor="middle" font-size="11" style="fill:var(--content)"&gt;Server&lt;/text&gt;&lt;text x="515" y="180" text-anchor="middle" font-size="10" style="fill:var(--content)"&gt;+ Session&lt;/text&gt;&lt;line x1="425" y1="170" x2="468" y2="170" style="stroke:var(--compare-b)" stroke-width="1.5" marker-end="url(#arrowB)"/&gt;&lt;text x="447" y="160" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;sticky&lt;/text&gt;&lt;rect x="580" y="95" width="45" height="30" rx="4" stroke-dasharray="3 3" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="602" y="114" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;Server&lt;/text&gt;&lt;rect x="580" y="215" width="45" height="30" rx="4" stroke-dasharray="3 3" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="602" y="234" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;Server&lt;/text&gt;&lt;text x="480" y="280" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;must always return to&lt;/text&gt;&lt;text x="480" y="296" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;same server holding session&lt;/text&gt;&lt;defs&gt;&lt;marker id="arrowA" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto"&gt;&lt;path d="M0,0 L6,3 L0,6 Z" style="fill:var(--compare-a)"/&gt;&lt;/marker&gt;&lt;marker id="arrowB" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto"&gt;&lt;path d="M0,0 L6,3 L0,6 Z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;/defs&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;Stateless&lt;/th&gt;
&lt;th&gt;Stateful&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Request self-sufficiency&lt;/td&gt;
&lt;td&gt;Each request carries all data needed to process it, independent of prior requests&lt;/td&gt;
&lt;td&gt;Each request depends on context accumulated from prior requests in the same session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State storage location&lt;/td&gt;
&lt;td&gt;Held externally (client token, database, cache) or not persisted at all&lt;/td&gt;
&lt;td&gt;Held in server memory or local storage tied to a specific server instance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Load balancing&lt;/td&gt;
&lt;td&gt;Any available server can handle any request; simple round-robin routing&lt;/td&gt;
&lt;td&gt;Requests must be routed to the specific server holding the session (sticky sessions)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Horizontal scaling&lt;/td&gt;
&lt;td&gt;Add or remove server instances freely with no coordination needed&lt;/td&gt;
&lt;td&gt;Requires state replication or migration before instances can be added or removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure recovery&lt;/td&gt;
&lt;td&gt;A crashed server loses nothing; the next request is simply retried elsewhere&lt;/td&gt;
&lt;td&gt;A crashed server can drop the active session unless state was replicated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Resource footprint per server&lt;/td&gt;
&lt;td&gt;Lower memory overhead since no per-client data is retained between requests&lt;/td&gt;
&lt;td&gt;Higher memory/storage overhead from tracking active sessions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical examples&lt;/td&gt;
&lt;td&gt;REST APIs, DNS lookups, serverless functions, CDN edge nodes&lt;/td&gt;
&lt;td&gt;Database connections, WebSocket sessions, FTP, multiplayer game servers&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;Stateless servers require no &lt;strong class="kw"&gt;session affinity&lt;/strong&gt;; stateful servers need sticky routing to reach the same instance.&lt;/li&gt;
&lt;li&gt;State in stateless systems lives in &lt;strong class="kw"&gt;external stores&lt;/strong&gt; or the client; state in stateful systems lives in server memory.&lt;/li&gt;
&lt;li&gt;Stateless architectures scale &lt;strong class="kw"&gt;horizontally&lt;/strong&gt; with ease, while stateful ones need state replication to scale out.&lt;/li&gt;
&lt;li&gt;A crashed stateless server loses nothing, but a crashed stateful server can drop an active &lt;strong class="kw"&gt;session&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;Stateless&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Horizontal Scaling vs Vertical Scaling: Growing Out vs Growing Up</title><link>https://comparison.metacog.co.kr/posts/2026-08-02-horizontal-scaling-vs-vertical-scaling-growing-out-vs-growin/</link><pubDate>Sun, 02 Aug 2026 23:47:18 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-02-horizontal-scaling-vs-vertical-scaling-growing-out-vs-growin/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Horizontal and vertical scaling are the two fundamental strategies for adding capacity to a system: one adds &lt;strong class="kw"&gt;more nodes&lt;/strong&gt; working in parallel, the other adds &lt;strong class="kw"&gt;more resources&lt;/strong&gt; to a single existing node. The choice shapes cost, downtime, fault tolerance, and how much your application architecture has to change to support it.&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;line x1="320" y1="20" x2="320" y2="340" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="4,4"/&gt;&lt;text x="160" y="36" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="600"&gt;Horizontal Scaling&lt;/text&gt;&lt;text x="480" y="36" text-anchor="middle" style="fill:var(--primary)" font-size="18" font-weight="600"&gt;Vertical Scaling&lt;/text&gt;&lt;rect x="125" y="58" width="70" height="32" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="79" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Load Balancer&lt;/text&gt;&lt;line x1="160" y1="90" x2="70" y2="148" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="160" y1="90" x2="145" y2="148" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="160" y1="90" x2="220" y2="148" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="160" y1="90" x2="295" y2="148" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;rect x="40" y="150" width="60" height="60" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="70" y="185" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;S1&lt;/text&gt;&lt;rect x="115" y="150" width="60" height="60" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="145" y="185" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;S2&lt;/text&gt;&lt;rect x="190" y="150" width="60" height="60" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="220" y="185" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;S3&lt;/text&gt;&lt;rect x="265" y="150" width="60" height="60" rx="4" style="fill:none;stroke:var(--compare-a)" stroke-width="1.5" stroke-dasharray="5,4"/&gt;&lt;text x="295" y="185" text-anchor="middle" style="fill:var(--compare-a)" font-size="18"&gt;+&lt;/text&gt;&lt;text x="160" y="245" text-anchor="middle" style="fill:var(--secondary)" font-size="12"&gt;scale out: add identical nodes&lt;/text&gt;&lt;text x="160" y="262" text-anchor="middle" style="fill:var(--secondary)" font-size="12"&gt;no downtime, redundant&lt;/text&gt;&lt;rect x="440" y="235" width="70" height="70" rx="4" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="475" y="265" text-anchor="middle" style="fill:var(--content)" font-size="12"&gt;Server&lt;/text&gt;&lt;text x="475" y="282" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;2 CPU / 4GB&lt;/text&gt;&lt;line x1="475" y1="230" x2="475" y2="200" style="stroke:var(--compare-b)" stroke-width="2"/&gt;&lt;polygon points="475,190 469,202 481,202" style="fill:var(--compare-b)"/&gt;&lt;rect x="390" y="90" width="170" height="105" rx="4" style="fill:none;stroke:var(--compare-b)" stroke-width="1.5" stroke-dasharray="5,4"/&gt;&lt;text x="475" y="135" text-anchor="middle" style="fill:var(--content)" font-size="13"&gt;Same Server&lt;/text&gt;&lt;text x="475" y="155" text-anchor="middle" style="fill:var(--content)" font-size="11"&gt;16 CPU / 64GB&lt;/text&gt;&lt;text x="475" y="172" text-anchor="middle" style="fill:var(--secondary)" font-size="11"&gt;upgraded&lt;/text&gt;&lt;text x="475" y="325" text-anchor="middle" style="fill:var(--secondary)" font-size="12"&gt;scale up: add CPU/RAM/disk&lt;/text&gt;&lt;text x="475" y="342" text-anchor="middle" style="fill:var(--secondary)" font-size="12"&gt;often needs downtime&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;Horizontal Scaling&lt;/th&gt;
&lt;th&gt;Vertical Scaling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mechanism&lt;/td&gt;
&lt;td&gt;Add more machines/nodes to the pool&lt;/td&gt;
&lt;td&gt;Add more CPU, RAM, or disk to an existing machine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation&lt;/td&gt;
&lt;td&gt;Requires a load balancer and clustering to distribute work&lt;/td&gt;
&lt;td&gt;Swap hardware or resize the VM/instance in place&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Downtime&lt;/td&gt;
&lt;td&gt;Typically none; new nodes join the pool live&lt;/td&gt;
&lt;td&gt;Usually requires a reboot or maintenance window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Application requirements&lt;/td&gt;
&lt;td&gt;App must be stateless or handle distributed state&lt;/td&gt;
&lt;td&gt;App can remain unaware, since it still runs on one node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost model&lt;/td&gt;
&lt;td&gt;Roughly linear cost per added commodity node&lt;/td&gt;
&lt;td&gt;Cost rises steeply at high-end hardware tiers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fault tolerance&lt;/td&gt;
&lt;td&gt;Redundant; a node failing doesn&amp;rsquo;t take the system down&lt;/td&gt;
&lt;td&gt;Single point of failure; that node failing is an outage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Capacity ceiling&lt;/td&gt;
&lt;td&gt;Practically unbounded, add nodes as needed&lt;/td&gt;
&lt;td&gt;Bounded by the largest machine/instance available&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use case&lt;/td&gt;
&lt;td&gt;Web-scale services, microservices, cloud-native apps&lt;/td&gt;
&lt;td&gt;Databases, legacy monoliths, short-term quick fixes&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;Horizontal scaling adds &lt;strong class="kw"&gt;more nodes&lt;/strong&gt; in parallel, while vertical scaling adds &lt;strong class="kw"&gt;more resources&lt;/strong&gt; to one existing node.&lt;/li&gt;
&lt;li&gt;Horizontal scaling needs a &lt;strong class="kw"&gt;load balancer&lt;/strong&gt; and app-level statelessness; vertical scaling needs no architectural change.&lt;/li&gt;
&lt;li&gt;Vertical scaling eventually hits a &lt;strong class="kw"&gt;hardware ceiling&lt;/strong&gt;; horizontal scaling can grow near-limitlessly.&lt;/li&gt;
&lt;li&gt;Vertical scaling usually requires &lt;strong class="kw"&gt;downtime&lt;/strong&gt; to resize, while horizontal scaling can add capacity live.&lt;/li&gt;
&lt;li&gt;Horizontal scaling improves &lt;strong class="kw"&gt;fault tolerance&lt;/strong&gt; through redundancy; vertical scaling keeps a single point of failure.&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;Horizontal Scaling&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>