<?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>Distributed-Systems on CS Theorems</title><link>https://cs.lozic.me/areas/distributed-systems/</link><description>Recent content in Distributed-Systems on CS Theorems</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Fri, 29 Oct 2027 12:00:00 +0100</lastBuildDate><atom:link href="https://cs.lozic.me/areas/distributed-systems/index.xml" rel="self" type="application/rss+xml"/><item><title>Consistent Hashing</title><link>https://cs.lozic.me/posts/t072-consistent-hashing/</link><pubDate>Fri, 29 Oct 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t072-consistent-hashing/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;You shard a cache across ten servers with the obvious rule:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;servers&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It works. Then you add an eleventh server, and &lt;code&gt;% 10&lt;/code&gt; becomes &lt;code&gt;% 11&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Every key now maps somewhere else. Not one tenth of them — essentially all of
them. A key landing on the same server after the change is a coincidence with
probability about $1/11$, so roughly 91% of your cache is instantly invalid.
Every request misses, every miss hits the database, and the database, sized for
a 95% cache hit rate, now receives twenty times its provisioned load and falls
over.&lt;/p&gt;</description></item><item><title>The CALM Theorem and CRDTs</title><link>https://cs.lozic.me/posts/t067-the-calm-theorem-and-crdts/</link><pubDate>Fri, 03 Sep 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t067-the-calm-theorem-and-crdts/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;Every distributed result so far has been a prohibition. Two Generals: no
agreement over a lossy channel. FLP: no deterministic asynchronous consensus.
Byzantine: not below $3f+1$. CAP: not all three.&lt;/p&gt;</description></item><item><title>The CAP Theorem and PACELC</title><link>https://cs.lozic.me/posts/t066-the-cap-theorem-and-pacelc/</link><pubDate>Fri, 27 Aug 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t066-the-cap-theorem-and-pacelc/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;Someone in a design review says &amp;ldquo;we&amp;rsquo;re AP, not CP,&amp;rdquo; and the room nods.&lt;/p&gt;
&lt;p&gt;Nobody asks which consistency, which availability, or what happens when there is
no partition, which is 99.9% of the time. The phrase has done the work of a
decision without containing one.&lt;/p&gt;</description></item><item><title>Paxos, Raft, and the Shape of Consensus</title><link>https://cs.lozic.me/posts/t064-paxos-raft-and-the-shape-of-consensus/</link><pubDate>Fri, 20 Aug 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t064-paxos-raft-and-the-shape-of-consensus/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;Your database has two nodes that both believe they are the primary.&lt;/p&gt;
&lt;p&gt;Each has been accepting writes. Each has a coherent log. Neither has crashed.
The old primary was declared dead by a health check that timed out during a GC
pause, a new one was elected, and then the old one woke up still holding what it
thinks is a valid lease. You now have two divergent histories of the same data
and no principled way to merge them, because both contain acknowledged writes
that customers were told had succeeded.&lt;/p&gt;</description></item><item><title>Quorum Intersection (R + W &gt; N)</title><link>https://cs.lozic.me/posts/t065-quorum-intersection/</link><pubDate>Fri, 13 Aug 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t065-quorum-intersection/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;You have three replicas of a value. A client writes &lt;code&gt;v2&lt;/code&gt; and gets an
acknowledgement. Another client reads and gets &lt;code&gt;v1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nothing crashed. No network partition healed badly. Both operations completed
successfully and reported success. The write went to one replica, the read came
from another, and the two never spoke.&lt;/p&gt;</description></item><item><title>The Byzantine Generals Problem</title><link>https://cs.lozic.me/posts/t063-the-byzantine-generals-problem/</link><pubDate>Fri, 18 Jun 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t063-the-byzantine-generals-problem/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;A node in your cluster is not down. It is worse than down.&lt;/p&gt;
&lt;p&gt;Its disk is returning corrupted blocks that pass the checksum because the
checksum is corrupted too. Or a NIC with a firmware bug is duplicating and
reordering frames. Or a bad memory module flipped a bit in a config value and
the node now believes it owns a shard it does not. Or someone has root on one
machine.&lt;/p&gt;</description></item><item><title>FLP Impossibility</title><link>https://cs.lozic.me/posts/t062-flp-impossibility/</link><pubDate>Fri, 11 Jun 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t062-flp-impossibility/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;Your cluster of five nodes elects a leader. It works. It has worked for a year.&lt;/p&gt;
&lt;p&gt;Then one afternoon a garbage collection pause on the leader runs for twelve
seconds. The followers time out, start an election, and elect a new leader. The
old leader wakes up, has no idea it was deposed, and keeps serving writes. For a
few hundred milliseconds you have two leaders, and if your fencing is not
airtight, two writes that should have been ordered land in an order nobody
chose.&lt;/p&gt;</description></item><item><title>Vector Clocks and Causal Consistency</title><link>https://cs.lozic.me/posts/t059-vector-clocks-and-causal-consistency/</link><pubDate>Fri, 04 Jun 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t059-vector-clocks-and-causal-consistency/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;You took the lesson from T058 and stopped trusting wall clocks. Every event now
carries a Lamport timestamp, and your writes are ordered by it. The vanishing
updates stopped.&lt;/p&gt;</description></item><item><title>Happens-Before and Lamport Clocks</title><link>https://cs.lozic.me/posts/t058-happens-before-and-lamport-clocks/</link><pubDate>Fri, 28 May 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t058-happens-before-and-lamport-clocks/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;Two writes to the same key. Which one wins?&lt;/p&gt;
&lt;p&gt;Your first instinct is timestamps: whichever has the later wall-clock time is
newer. This works in testing. In production you get a bug report saying an
update vanished, and when you dig in, node B&amp;rsquo;s clock was 40 ms behind node A&amp;rsquo;s,
so B&amp;rsquo;s &lt;em&gt;later&lt;/em&gt; write carried an &lt;em&gt;earlier&lt;/em&gt; timestamp and lost. NTP is running.
NTP does not make clocks identical, it makes them close, and &amp;ldquo;close&amp;rdquo; is not
&amp;ldquo;ordered.&amp;rdquo;&lt;/p&gt;</description></item><item><title>Balls Into Bins and the Power of Two Choices</title><link>https://cs.lozic.me/posts/t009-balls-into-bins/</link><pubDate>Fri, 12 Feb 2027 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t009-balls-into-bins/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;You have 100 backends and a load balancer hashing request IDs to pick one.
Expected load per backend is exactly 1%, and you have checked the hash is good.&lt;/p&gt;</description></item><item><title>The Two Generals Problem</title><link>https://cs.lozic.me/posts/t061-the-two-generals-problem/</link><pubDate>Fri, 30 Oct 2026 12:00:00 +0100</pubDate><guid>https://cs.lozic.me/posts/t061-the-two-generals-problem/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;You call the payment API. The request goes out. Nothing comes back.&lt;/p&gt;
&lt;p&gt;Did the charge happen? You genuinely do not know. Retrying might double-charge
the customer. Not retrying might drop the payment. There is no third option
available, and no amount of care in your client library creates one.&lt;/p&gt;</description></item><item><title>Gustafson's Law and the Universal Scalability Law</title><link>https://cs.lozic.me/posts/t082-gustafsons-law-and-the-usl/</link><pubDate>Fri, 25 Sep 2026 12:00:00 +0200</pubDate><guid>https://cs.lozic.me/posts/t082-gustafsons-law-and-the-usl/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;
&lt;p&gt;Two measurements that both look like they break the previous post.&lt;/p&gt;
&lt;p&gt;The first: your Spark job takes four hours on ten nodes. You move it to a
hundred nodes and it still takes four hours — but it is now processing ten times
the data. &lt;a href="https://cs.lozic.me/posts/t081-amdahls-law/"&gt;T081&lt;/a&gt; said the ceiling was
20×, and nobody hit a ceiling.&lt;/p&gt;</description></item></channel></rss>