4.4.26 · D3Databases

Worked examples — BASE vs ACID

4,195 words19 min readBack to topic

This page is the hands-on companion to the parent BASE vs ACID note. There we built the ideas; here we run them through every kind of situation a database can face — every "quadrant" of the design space, the degenerate corners (zero replicas, network fully down), the limiting cases (infinite delay, instant sync), a real-world word problem, and an exam twist.

Before we start, some tiny bits of vocabulary so no symbol or acronym appears unearned.

Two more labels come straight from the CAP theorem and get used on every line below, so let's define them now:

We measure two costs, exactly as the parent's decision rule defined them:


The scenario matrix

Think of the design space as a 2×2 grid. The columns are what kind of data you hold — money-like (a wrong value costs a lot) versus feed-like (staleness is cheap). The rows are what the network is doinghealthy versus partitioned (split). Each of the four inner cells has its own worked example; then we bolt on the degenerate corners (conflicting writes, zero replicas) and the limiting edge (delay → 0 or → ∞), plus a word problem and an exam twist.

The figure below draws that exact grid — read it before the table:

Figure — BASE vs ACID

Now the same grid in table form, with each axis labelled explicitly:

↓ Network \ Data → Money-like (Cwrong high) Feed-like (Cdown high)
Healthy Cell A — ACID happy path (Ex 1) Cell C — BASE happy path (Ex 3)
Partitioned Cell B — ACID/CP refuses (Ex 2) Cell D — BASE/AP answers, converges (Ex 4)

And the extra corners that live outside the clean 2×2:

Cell Case class What makes it tricky Worked in
E Degenerate: conflicting writes two replicas change the same key while split Ex 5
F Degenerate: zero replicas reachable what does each contract do with nothing to talk to? Ex 6
G Limiting: sync delay → 0 vs → ∞ when does BASE "become" ACID, or never converge? Ex 7
H Real-world word problem pick the contract from the cost numbers Ex 8
I Exam twist: mixed system + false CAP claim one app using both contracts Ex 9

Every cell A–I gets at least one fully worked example below.


Example 1 — Cell A: ACID happy path (atomicity that still matters)

  1. Start the transaction. We write BEGIN. Why this step? It marks both updates as one indivisible unit — Atomicity. Without it, a crash between the two UPDATEs could leave money half-moved.
  2. Debit A: . Why this step? This is the "money leaves" half.
  3. Credit B: . Why this step? The "money arrives" half — it must be glued to step 2.
  4. Commit. Why this step? COMMIT makes it Durable (survives a crash) and reveals the new state atomically to other readers (Isolation hides the in-between).

Result: A = \150B = $50$.


Example 2 — Cell B: ACID under partition (CP refuses)

To keep both replicas correct at once, ACID uses two-phase commit: a coordinator asks all participants "can you commit?" and only if everyone says yes does it commit.

  1. Phase 1 (prepare). Coordinator asks and to prepare. Why this step? No one commits until everyone agrees — this is how Atomicity survives across machines.
  2. is unreachable (partition). The coordinator gets no "yes" from . Why this matters: one silent participant means the coordinator cannot know if will apply the credit.
  3. Abort. Coordinator tells to roll back the debit. Why this step? Committing only the debit would violate conservation (money vanishes). CP (correct, may refuse) chooses correctness over availability.

Result: the transfer is refused; stays $200, stays $0.


Example 3 — Cell C: BASE happy path (fast write, brief stale read)

First, the piece of BASE jargon this example rests on:

  1. Write locally, return now. becomes and answers you instantly. Why this step? Basically Available — never make the user wait for global agreement.
  2. Others are momentarily stale. still show for a moment. Why this step? This is soft state (just defined) — the value differs across replicas even though no new "like" happened on ; a background sync is pending.
  3. Background gossip. pushes the update; soon . Why this step? Eventual consistency — with no new writes, all three converge.

Example 4 — Cell D: BASE under partition (AP both answer, then converge)

Before the example, expand the acronym it needs:

  1. Both stay available. During the split reports , reports . Why this step? AP (always answers, may be stale) means answer anyway — no side refuses.
  2. Track the deltas, not the totals. Each side remembers "I added 5" / "I added 3." Why this step? Views are commutative and additive — a counter CRDT (just defined) merges by summing the increments, so no data is lost.
  3. Heal & merge. Converged value . Why this step? Merging deltas gives the true count regardless of the order the sides sync — this is eventual consistency done right.

Example 5 — Cell E (degenerate): conflicting writes to the same key

  1. No commutativity here. Name is last-value-wins, not additive. Why this step? You can't merge "Samuel" + "Sammy" by summation — the operations conflict.
  2. Break the tie deterministically. Attach a timestamp (or version) to each write. Say 's write is at , 's at . Why this step? A total order lets every replica independently pick the same winner → convergence.
  3. Converge on the later write. , so all replicas settle on "Sammy". The "Samuel" write is overwritten (lost). Why this step? AP accepts that one conflicting write may be dropped — that is the price of never blocking.

Example 6 — Cell F (degenerate): zero replicas reachable

First, a clean distinction so we don't confuse two ideas:

  1. ACID/CP, zero replicas reachable: it cannot confirm it holds the latest committed write, so it refuses / errors. Why this step? CP (correct, may refuse) never risks stale data; with zero confirmable replicas, correctness can't be guaranteed, so availability is sacrificed. Reads served = 0.
  2. BASE/AP, at least one replica reachable: it serves that replica's value even if possibly stale. Why this step? AP (always answers) prioritizes responding. But in this scenario no replica is reachable, so this branch does not apply — go to step 3.
  3. BASE/AP with truly zero replicas reachable: the database itself has nothing to serve — it cannot invent data, so it errors just like CP from the database's own store. Why this matters: availability cannot create information from nothing. AP beats CP only when it has some reachable replica; with genuinely zero, both fail to serve fresh data.
  4. Part (c) — the client cache: if the client kept its own cache (outside the database), it may show a last-known value. Why this is a separate part of the forecast: that resilience comes from client-side caching, not from the database's replication. It is a design you add on top, not a property of AP itself.

Example 7 — Cell G (limiting): sync delay → 0 and → ∞

The figure below plots the stale window (how long replicas may disagree) against this delay — glance at it, then follow the steps:

Figure — BASE vs ACID
  1. Limit . The stale window shrinks to nothing: every replica sees a write "instantly." Why this matters: BASE now behaves like strong consistency — indistinguishable from ACID's immediacy on reads. So ACID is the idealization that a healthy network never quite reaches (the mint floor in the figure).
  2. Limit . Writes never propagate. Why this matters: "eventual" never arrives — replicas can disagree forever. This is exactly a permanent partition; BASE's promise ("with no new writes, converge") is void because messages don't flow.
  3. Real life sits between. Typically is milliseconds to seconds — small, non-zero (the butter band). Why this matters: that's why a like-count is "off by one for 2 seconds" and not "off forever." The consistency level you choose slides you along this axis.

Example 8 — Cell H: real-world word problem (pick the contract from numbers)

  1. Seat reservation costs: C_{wrong} = \400C_{down} \approx $0$ (a short wait is fine). Why this step? Plug into the decision rule.
  2. Apply the rule to seats: ACID/CP. Refuse or wait rather than sell the same seat twice.
  3. Feed costs: C_{wrong} \approx \0C_{down} = $5000$ (outage during launch). Why this step? Same rule, opposite numbers.
  4. Apply the rule to feed: BASE/AP. Always answer, reconcile later.

Example 9 — Cell I: exam twist (mixed system + a false CAP claim)

  1. The mix is legal — mark it correct. Using ACID for checkout and BASE for the feed is standard (Ex 8 proved it numerically). Why this step? The label describes the contract per dataset, not the whole app; you match each guarantee to that data's cost of being wrong.
  2. Spot the false claim. CAP says P is not a design choice — partitions are a fact of distributed networking. Why this step? You only get to pick between C and A when a partition happens; you never "turn P off," so "dropped P to get C and A everywhere" is impossible.
  3. Count honestly. Without a partition all three (C, A, P) can appear to hold — but that is not a guarantee, it's just "nothing has failed yet." The theorem's claim is about the partition case: there you keep at most 2 of 3, and since P is forced, the real choice is C or A. Why this step? This turns the vague "2 of 3" into a concrete count.
  4. Corrected statement. During a partition the valid pairs are exactly {C, P} (ACID/CP checkout) and {A, P} (BASE/AP feed) — two options. The claimed {C, A} with P removed is invalid. Why this step? It names precisely which pairs survive and which is the illusion.

Recall Quick self-test (hidden)

During a partition, an additive counter can merge losslessly but a single-overwrite field cannot — why? ::: A counter's operations (increments) are commutative/associative so summing deltas is order-independent; an overwrite conflicts, so one write must win and the other is lost. As BASE's propagation delay , which contract does it resemble? ::: Strong/immediate consistency — i.e. ACID-like reads. Two apps, one checkout (double-book costs $400) and one feed (outage costs $5000): which is CP, which is AP? ::: Checkout = CP (ACID), feed = AP (BASE). Can you design a distributed system that "drops P"? ::: No — partitions are a fact of the network; you only choose between C and A when one occurs. What is the difference between a replica and a client cache? ::: A replica is a server-side copy the database syncs; a client cache is a separate copy the caller keeps outside the database's replication. What does the acronym CRDT stand for? ::: Conflict-Free Replicated Data Type — replicas update independently and merge with no conflict (e.g. a counter that sums increments).


Flashcards

What does CP stand for and mean?
Consistency + Partition tolerance — stays correct and survives splits, but may refuse/block (gives up Availability)
What does AP stand for and mean?
Availability + Partition tolerance — always answers and survives splits, but answers may be stale (gives up immediate Consistency)
Under a network partition, what does an ACID/CP transfer do?
Refuses/aborts (rolls back) rather than commit possibly-wrong data
How does a BASE counter converge after a partition heals?
It sums the increments made on each side (commutative merge), losing nothing
How does a BASE single-overwrite field resolve a conflict?
Last-value-wins by timestamp/version; the earlier conflicting write is dropped
What does "soft state" mean in BASE?
A stored value may differ between replicas and change on a replica without a new write there, because a background sync is still in flight
What does CRDT stand for?
Conflict-Free Replicated Data Type — replicas update independently and merge without conflict
What does BASE resemble as sync delay d → 0?
Strong/immediate consistency (ACID-like)
What happens to BASE as sync delay d → ∞?
Never converges — equivalent to a permanent partition
If cost of wrong data is $400 and cost of downtime ≈ $0, choose?
ACID/CP
Can one application use both ACID and BASE?
Yes — match the contract to each dataset's cost of being wrong
Why can't you "drop P" in CAP?
Partitions are a networking fact, not a design choice; you only pick C vs A when one happens
Replica vs client cache?
Replica = server-side copy synced by the DB; client cache = caller's own copy outside the DB's replication