<?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>Database on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/database/</link><description>Recent content in Database on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 06 Sep 2026 09:49:36 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/database/index.xml" rel="self" type="application/rss+xml"/><item><title>Optimistic vs Pessimistic Locking: Detect-at-Commit vs Lock-Before-Access</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-optimistic-vs-pessimistic-locking-detect-at-commit-vs-lock-b/</link><pubDate>Sun, 06 Sep 2026 09:49:36 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-optimistic-vs-pessimistic-locking-detect-at-commit-vs-lock-b/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;Both are concurrency-control strategies for preventing lost updates when multiple transactions touch the same data, but they differ in when they deal with conflict. Optimistic locking assumes collisions are rare and only performs a &lt;strong class="kw"&gt;version check&lt;/strong&gt; at commit time, while pessimistic locking assumes collisions are likely and takes an &lt;strong class="kw"&gt;exclusive lock&lt;/strong&gt; before any read or write proceeds.&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="28" font-size="18" font-weight="bold" text-anchor="middle" style="fill:var(--primary)"&gt;Optimistic&lt;/text&gt;
&lt;text x="480" y="28" font-size="18" font-weight="bold" text-anchor="middle" style="fill:var(--primary)"&gt;Pessimistic&lt;/text&gt;
&lt;line x1="320" y1="45" x2="320" y2="335" stroke-width="1" stroke-dasharray="4,4" style="stroke:var(--border)"/&gt;
&lt;rect x="115" y="55" width="90" height="38" rx="4" stroke-width="1.5" style="fill:var(--compare-a-soft);stroke:var(--compare-a)"/&gt;
&lt;text x="160" y="79" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Record (v1)&lt;/text&gt;
&lt;text x="160" y="105" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;no lock taken&lt;/text&gt;
&lt;line x1="140" y1="93" x2="75" y2="140" stroke-width="1.5" style="stroke:var(--compare-a)"/&gt;
&lt;line x1="180" y1="93" x2="245" y2="140" stroke-width="1.5" style="stroke:var(--compare-a)"/&gt;
&lt;rect x="30" y="140" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-a-soft);stroke:var(--compare-a)"/&gt;
&lt;text x="75" y="165" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Txn A&lt;/text&gt;
&lt;rect x="200" y="140" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-a-soft);stroke:var(--compare-a)"/&gt;
&lt;text x="245" y="165" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Txn B&lt;/text&gt;
&lt;line x1="75" y1="180" x2="75" y2="225" stroke-width="1.5" style="stroke:var(--compare-a)"/&gt;
&lt;line x1="245" y1="180" x2="245" y2="225" stroke-width="1.5" stroke-dasharray="3,3" style="stroke:var(--border)"/&gt;
&lt;rect x="30" y="225" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-a-soft);stroke:var(--compare-a)"/&gt;
&lt;text x="75" y="245" font-size="12" text-anchor="middle" style="fill:var(--content)"&gt;v1 &amp;#8594; v2&lt;/text&gt;
&lt;text x="75" y="259" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;committed&lt;/text&gt;
&lt;rect x="200" y="225" width="90" height="40" rx="4" stroke-width="1.5" stroke-dasharray="3,3" style="fill:none;stroke:var(--border)"/&gt;
&lt;text x="245" y="245" font-size="12" text-anchor="middle" style="fill:var(--content)"&gt;v1 &amp;#8800; v2&lt;/text&gt;
&lt;text x="245" y="259" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;conflict, retry&lt;/text&gt;
&lt;text x="160" y="310" font-size="11" text-anchor="middle" style="fill:var(--secondary)"&gt;conflict caught at commit time&lt;/text&gt;
&lt;rect x="470" y="34" width="20" height="14" rx="2" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;path d="M474,34 v-5 a6,6 0 0 1 12,0 v5" stroke-width="1.5" style="fill:none;stroke:var(--compare-b)"/&gt;
&lt;rect x="435" y="55" width="90" height="38" rx="4" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;text x="480" y="79" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Record&lt;/text&gt;
&lt;line x1="460" y1="93" x2="395" y2="140" stroke-width="1.5" style="stroke:var(--compare-b)"/&gt;
&lt;line x1="500" y1="93" x2="565" y2="140" stroke-width="1.5" stroke-dasharray="3,3" style="stroke:var(--border)"/&gt;
&lt;text x="545" y="120" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;blocked&lt;/text&gt;
&lt;rect x="350" y="140" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;text x="395" y="157" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Txn A&lt;/text&gt;
&lt;text x="395" y="171" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;holds lock&lt;/text&gt;
&lt;rect x="520" y="140" width="90" height="40" rx="4" stroke-width="1.5" stroke-dasharray="3,3" style="fill:none;stroke:var(--border)"/&gt;
&lt;text x="565" y="157" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Txn B&lt;/text&gt;
&lt;text x="565" y="171" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;waiting&lt;/text&gt;
&lt;line x1="395" y1="180" x2="395" y2="225" stroke-width="1.5" style="stroke:var(--compare-b)"/&gt;
&lt;line x1="565" y1="180" x2="565" y2="225" stroke-width="1.5" style="stroke:var(--compare-b)"/&gt;
&lt;rect x="350" y="225" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;text x="395" y="245" font-size="11" text-anchor="middle" style="fill:var(--content)"&gt;commits &amp;amp;&lt;/text&gt;
&lt;text x="395" y="259" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;releases lock&lt;/text&gt;
&lt;rect x="520" y="225" width="90" height="40" rx="4" stroke-width="1.5" style="fill:var(--compare-b-soft);stroke:var(--compare-b)"/&gt;
&lt;text x="565" y="245" font-size="11" text-anchor="middle" style="fill:var(--content)"&gt;acquires lock&lt;/text&gt;
&lt;text x="565" y="259" font-size="10" text-anchor="middle" style="fill:var(--secondary)"&gt;then runs&lt;/text&gt;
&lt;text x="480" y="310" font-size="11" text-anchor="middle" style="fill:var(--secondary)"&gt;conflict prevented up front&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;Optimistic Locking&lt;/th&gt;
&lt;th&gt;Pessimistic Locking&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Access phase&lt;/td&gt;
&lt;td&gt;No lock taken; any transaction can read or begin writing the row immediately&lt;/td&gt;
&lt;td&gt;Lock acquired (e.g. SELECT FOR UPDATE) before the transaction reads or writes the row&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrent access&lt;/td&gt;
&lt;td&gt;Other transactions freely read and write the same row in parallel&lt;/td&gt;
&lt;td&gt;Other transactions attempting the same row must wait for the lock holder to finish&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conflict detection timing&lt;/td&gt;
&lt;td&gt;Deferred until commit, via a version number, timestamp, or hash comparison&lt;/td&gt;
&lt;td&gt;Not needed as a separate step; the lock physically prevents overlapping access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;On conflict&lt;/td&gt;
&lt;td&gt;Commit is rejected; the transaction is rolled back and typically retried&lt;/td&gt;
&lt;td&gt;No conflict occurs; the waiting transaction simply blocks until the lock is released&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Implementation mechanism&lt;/td&gt;
&lt;td&gt;Application-level version column checked in the UPDATE&amp;rsquo;s WHERE clause&lt;/td&gt;
&lt;td&gt;Database-level row or table locks managed by the lock manager&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throughput under low contention&lt;/td&gt;
&lt;td&gt;High; no blocking overhead when collisions are rare&lt;/td&gt;
&lt;td&gt;Lower; locking overhead is paid even when no real conflict would occur&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Behavior under high contention&lt;/td&gt;
&lt;td&gt;Retry storms and wasted work as many transactions repeatedly fail and re-run&lt;/td&gt;
&lt;td&gt;Orderly queueing keeps correctness but serializes work and limits parallelism&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deadlock risk&lt;/td&gt;
&lt;td&gt;None, since no locks are ever held&lt;/td&gt;
&lt;td&gt;Possible when transactions acquire multiple locks in inconsistent order&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;Optimistic locking detects conflicts at &lt;strong class="kw"&gt;commit time&lt;/strong&gt;; pessimistic locking prevents them via &lt;strong class="kw"&gt;upfront locking&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Optimistic locking never blocks other transactions, it only forces a &lt;strong class="kw"&gt;retry&lt;/strong&gt; on collision.&lt;/li&gt;
&lt;li&gt;Pessimistic locking holds an &lt;strong class="kw"&gt;exclusive lock&lt;/strong&gt; for the transaction&amp;rsquo;s full duration, serializing access to the row.&lt;/li&gt;
&lt;li&gt;Optimistic locking carries no &lt;strong class="kw"&gt;deadlock&lt;/strong&gt; risk because it never holds locks.&lt;/li&gt;
&lt;li&gt;Pessimistic locking trades raw throughput for &lt;strong class="kw"&gt;predictability&lt;/strong&gt; when contention is heavy.&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;Optimistic Locking&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>SQL vs NoSQL: Relational Tables vs Flexible Data Models</title><link>https://comparison.metacog.co.kr/posts/2026-09-06-sql-vs-nosql-relational-tables-vs-flexible-data-models/</link><pubDate>Sun, 06 Sep 2026 09:37:35 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-09-06-sql-vs-nosql-relational-tables-vs-flexible-data-models/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;SQL and NoSQL databases differ in how they structure, store, and query data: SQL enforces a &lt;strong class="kw"&gt;fixed schema&lt;/strong&gt; of related tables joined by keys, while NoSQL favors a &lt;strong class="kw"&gt;flexible schema&lt;/strong&gt; optimized for scale and varied data shapes. The choice affects everything from how you model relationships to how the system behaves under heavy write load or schema change.&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="150" y="36" text-anchor="middle" font-size="20" style="fill:var(--primary)"&gt;SQL&lt;/text&gt;&lt;text x="490" y="36" text-anchor="middle" font-size="20" style="fill:var(--primary)"&gt;NoSQL&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="40" y="70" width="160" height="90" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="40" y1="100" x2="200" y2="100" style="stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;line x1="120" y1="70" x2="120" y2="160" style="stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;text x="48" y="90" font-size="12" style="fill:var(--primary)"&gt;Users&lt;/text&gt;&lt;text x="48" y="118" font-size="11" style="fill:var(--content)"&gt;id&lt;/text&gt;&lt;text x="128" y="118" font-size="11" style="fill:var(--content)"&gt;name&lt;/text&gt;&lt;text x="48" y="140" font-size="11" style="fill:var(--content)"&gt;1&lt;/text&gt;&lt;text x="128" y="140" font-size="11" style="fill:var(--content)"&gt;Alice&lt;/text&gt;&lt;rect x="40" y="200" width="160" height="110" rx="4" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;line x1="40" y1="230" x2="200" y2="230" style="stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;line x1="100" y1="200" x2="100" y2="310" style="stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;line x1="150" y1="200" x2="150" y2="310" style="stroke:var(--compare-a)" stroke-width="1"/&gt;&lt;text x="48" y="220" font-size="12" style="fill:var(--primary)"&gt;Orders&lt;/text&gt;&lt;text x="48" y="248" font-size="10" style="fill:var(--content)"&gt;id&lt;/text&gt;&lt;text x="106" y="248" font-size="10" style="fill:var(--content)"&gt;user_id&lt;/text&gt;&lt;text x="156" y="248" font-size="10" style="fill:var(--content)"&gt;item&lt;/text&gt;&lt;text x="48" y="270" font-size="10" style="fill:var(--content)"&gt;9&lt;/text&gt;&lt;text x="106" y="270" font-size="10" style="fill:var(--content)"&gt;1&lt;/text&gt;&lt;text x="156" y="270" font-size="10" style="fill:var(--content)"&gt;Book&lt;/text&gt;&lt;path d="M 106 200 Q 106 165 118 160" fill="none" style="stroke:var(--compare-a)" stroke-width="1.5" stroke-dasharray="3 3"/&gt;&lt;text x="210" y="180" font-size="10" style="fill:var(--secondary)"&gt;foreign key join&lt;/text&gt;&lt;rect x="380" y="70" width="220" height="240" rx="10" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="396" y="96" font-size="12" style="fill:var(--primary)"&gt;{&lt;/text&gt;&lt;text x="412" y="118" font-size="11" style="fill:var(--content)"&gt;"id": 1,&lt;/text&gt;&lt;text x="412" y="140" font-size="11" style="fill:var(--content)"&gt;"name": "Alice",&lt;/text&gt;&lt;text x="412" y="162" font-size="11" style="fill:var(--content)"&gt;"orders": [&lt;/text&gt;&lt;text x="432" y="184" font-size="11" style="fill:var(--content)"&gt;{ "item": "Book" },&lt;/text&gt;&lt;text x="432" y="206" font-size="11" style="fill:var(--content)"&gt;{ "item": "Pen" }&lt;/text&gt;&lt;text x="412" y="228" font-size="11" style="fill:var(--content)"&gt;]&lt;/text&gt;&lt;text x="396" y="250" font-size="12" style="fill:var(--primary)"&gt;}&lt;/text&gt;&lt;text x="490" y="290" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;embedded, self-contained document&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;SQL&lt;/th&gt;
&lt;th&gt;NoSQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data model&lt;/td&gt;
&lt;td&gt;Rows in normalized tables with fixed columns&lt;/td&gt;
&lt;td&gt;Documents, key-value pairs, wide columns, or graphs with flexible fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema definition&lt;/td&gt;
&lt;td&gt;Defined upfront; changes require migrations (ALTER TABLE)&lt;/td&gt;
&lt;td&gt;Schema-on-read; fields can vary per record without migration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relationships&lt;/td&gt;
&lt;td&gt;Modeled explicitly via foreign keys and JOINs&lt;/td&gt;
&lt;td&gt;Modeled by embedding related data or denormalizing across documents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Query language&lt;/td&gt;
&lt;td&gt;Standardized SQL across most vendors&lt;/td&gt;
&lt;td&gt;Vendor-specific APIs or query languages (e.g. MongoDB query, CQL)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Transactions &amp;amp; consistency&lt;/td&gt;
&lt;td&gt;ACID guarantees across multi-row/multi-table operations&lt;/td&gt;
&lt;td&gt;Often eventual consistency; ACID typically limited to single-document scope&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling approach&lt;/td&gt;
&lt;td&gt;Primarily vertical scaling; sharding is possible but complex&lt;/td&gt;
&lt;td&gt;Built for horizontal scaling via native partitioning/sharding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best-fit workload&lt;/td&gt;
&lt;td&gt;Structured data with complex, ad-hoc relational queries&lt;/td&gt;
&lt;td&gt;High-volume, high-velocity data with evolving or hierarchical structure&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;SQL requires a &lt;strong class="kw"&gt;fixed schema&lt;/strong&gt; agreed on before writing data; NoSQL allows each record to carry its own shape&lt;/li&gt;
&lt;li&gt;Relational databases resolve relationships through &lt;strong class="kw"&gt;JOINs&lt;/strong&gt;, while NoSQL typically resolves them through &lt;strong class="kw"&gt;embedding&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;SQL guarantees &lt;strong class="kw"&gt;ACID transactions&lt;/strong&gt; across tables; most NoSQL systems trade that for &lt;strong class="kw"&gt;eventual consistency&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;SQL systems scale primarily by &lt;strong class="kw"&gt;scaling up&lt;/strong&gt; hardware; NoSQL systems are designed to &lt;strong class="kw"&gt;scale out&lt;/strong&gt; across nodes&lt;/li&gt;
&lt;li&gt;Query language is a &lt;strong class="kw"&gt;standardized&lt;/strong&gt; across SQL vendors, whereas NoSQL query APIs are largely &lt;strong class="kw"&gt;proprietary&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;SQL&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Managed Database vs Self-Hosted Database: Who Runs the Stack</title><link>https://comparison.metacog.co.kr/posts/2026-08-03-managed-database-vs-self-hosted-database-who-runs-the-stack/</link><pubDate>Mon, 03 Aug 2026 06:30:21 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-03-managed-database-vs-self-hosted-database-who-runs-the-stack/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;A managed database hands the operating system, patching, backups, and failover to a &lt;strong class="kw"&gt;cloud provider&lt;/strong&gt;, while a self-hosted database keeps the entire stack under your team&amp;rsquo;s &lt;strong class="kw"&gt;direct control&lt;/strong&gt;. The choice trades operational convenience against flexibility, cost structure, and how much low-level tuning you&amp;rsquo;re allowed to do.&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="30" text-anchor="middle" font-size="16" font-weight="bold" style="fill:var(--primary)"&gt;Managed Database&lt;/text&gt;&lt;text x="480" y="30" text-anchor="middle" font-size="16" font-weight="bold" style="fill:var(--primary)"&gt;Self-Hosted Database&lt;/text&gt;&lt;rect x="60" y="55" width="200" height="45" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="160" y="82" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Application / Queries&lt;/text&gt;&lt;rect x="50" y="110" width="220" height="195" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="128" text-anchor="middle" font-size="12" font-weight="600" style="fill:var(--compare-a)"&gt;Provider Manages&lt;/text&gt;&lt;rect x="70" y="140" width="180" height="40" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="160" y="164" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;DB Engine&lt;/text&gt;&lt;rect x="70" y="195" width="180" height="40" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="160" y="219" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Operating System&lt;/text&gt;&lt;rect x="70" y="250" width="180" height="40" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="160" y="274" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Hardware / Storage&lt;/text&gt;&lt;text x="160" y="330" text-anchor="middle" font-size="11" style="fill:var(--secondary)"&gt;Less control, less toil&lt;/text&gt;&lt;rect x="370" y="55" width="220" height="250" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="73" text-anchor="middle" font-size="12" font-weight="600" style="fill:var(--compare-b)"&gt;You Manage Everything&lt;/text&gt;&lt;rect x="390" y="85" width="180" height="40" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="480" y="109" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Application / Queries&lt;/text&gt;&lt;rect x="390" y="140" width="180" height="40" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="480" y="164" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;DB Engine&lt;/text&gt;&lt;rect x="390" y="195" width="180" height="40" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="480" y="219" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Operating System&lt;/text&gt;&lt;rect x="390" y="250" width="180" height="40" rx="4" style="fill:none;stroke:var(--border)" stroke-width="1.5"/&gt;&lt;text x="480" y="274" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Hardware / Storage&lt;/text&gt;&lt;text x="480" y="330" text-anchor="middle" font-size="11" style="fill:var(--secondary)"&gt;More control, more toil&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;Managed Database&lt;/th&gt;
&lt;th&gt;Self-Hosted Database&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Provisioning &amp;amp; setup&lt;/td&gt;
&lt;td&gt;Spin up via console or API in minutes; provider installs and configures the engine&lt;/td&gt;
&lt;td&gt;Manually install and configure the OS, storage, and database software yourself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration &amp;amp; tuning access&lt;/td&gt;
&lt;td&gt;Limited to exposed parameters and flags; some engine internals and OS access are locked&lt;/td&gt;
&lt;td&gt;Full root or admin access to every config file, kernel setting, and storage layout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling&lt;/td&gt;
&lt;td&gt;Resize compute or add read replicas with a click or API call; provider automates the process&lt;/td&gt;
&lt;td&gt;Provision new hardware and reconfigure sharding or replication topology yourself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backups &amp;amp; recovery&lt;/td&gt;
&lt;td&gt;Automated snapshots and point-in-time restore built into the service&lt;/td&gt;
&lt;td&gt;You script, schedule, and test your own backup and restore procedures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patching &amp;amp; upgrades&lt;/td&gt;
&lt;td&gt;Provider applies OS and engine security patches on a maintenance schedule&lt;/td&gt;
&lt;td&gt;You plan, test, and execute every patch and major version upgrade&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High availability &amp;amp; failover&lt;/td&gt;
&lt;td&gt;Multi-AZ replication and automatic failover configured with a toggle&lt;/td&gt;
&lt;td&gt;You design, build, and test the replication and failover setup yourself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Monitoring &amp;amp; support&lt;/td&gt;
&lt;td&gt;Built-in dashboards and alerts, plus vendor support tickets for engine-level issues&lt;/td&gt;
&lt;td&gt;You assemble your own monitoring stack; support is internal or community-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost model&lt;/td&gt;
&lt;td&gt;Higher per-hour price that bundles operational labor into the bill&lt;/td&gt;
&lt;td&gt;Lower raw infrastructure cost but a hidden cost in engineering time&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;Managed services abstract patching and OS maintenance behind a &lt;strong class="kw"&gt;provider&lt;/strong&gt; SLA.&lt;/li&gt;
&lt;li&gt;Self-hosted setups grant full &lt;strong class="kw"&gt;root access&lt;/strong&gt; to tune kernel, storage, and engine internals.&lt;/li&gt;
&lt;li&gt;Failover and multi-AZ replication are &lt;strong class="kw"&gt;automated&lt;/strong&gt; in managed offerings but hand-built elsewhere.&lt;/li&gt;
&lt;li&gt;Cost shifts from engineering hours to a recurring &lt;strong class="kw"&gt;subscription fee&lt;/strong&gt; with managed databases.&lt;/li&gt;
&lt;li&gt;Self-hosting permits any &lt;strong class="kw"&gt;custom extension&lt;/strong&gt; or fork that managed platforms often restrict.&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;Managed Database&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>