All Posts

BASE Theorem Explained: How it Stands Against ACID

ACID guarantees consistency. BASE guarantees availability. We explain the trade-offs between SQL...

Abstract AlgorithmsAbstract Algorithms
··15 min read
Share
Share on X / Twitter
Share on LinkedIn
Copy link

TLDR

TLDR: ACID (Atomicity, Consistency, Isolation, Durability) is the gold standard for banking. BASE (Basically Available, Soft state, Eventual consistency) is the standard for social media. BASE intentionally sacrifices instant accuracy in exchange for high availability and horizontal scale.


📖 Why Your Bank and Twitter Run on Different Consistency Rules

When you transfer $100, you need a guarantee: the money leaves your account and lands in the recipient's account as one atomic operation. A partial success is worse than no operation at all. This is ACID.

When you post a tweet, you do not care if a user in Singapore sees it 500 ms later than a user in New York. What you care about is that the system stays up and the tweet eventually propagates everywhere. This is BASE.

The two models exist because of the CAP theorem: you cannot have strong consistency, perfect availability, AND partition tolerance at the same time. ACID systems (like PostgreSQL) choose consistency. BASE systems (like DynamoDB, Cassandra) choose availability.


🔍 What ACID and BASE Actually Stand For

Before diving into mechanics, let's decode the acronyms in plain language — because both names are deliberately chosen contrasts.

ACID stands for:

  • A — Atomicity: A transaction is all-or-nothing. Either every step succeeds, or the whole thing is rolled back as if it never happened.
  • C — Consistency: A committed transaction always leaves the database in a valid state. It can never violate defined rules or constraints.
  • I — Isolation: Concurrent transactions do not bleed into each other. Each sees a snapshot of the world as if it were running alone.
  • D — Durability: Once committed, data survives crashes, power failures, and restarts. It is written to persistent storage before the system acknowledges success.

BASE stands for:

  • BA — Basically Available: The system always responds to requests, even if the response reflects slightly stale data. Availability is prioritised over perfect accuracy.
  • S — Soft State: The current state of the system is not guaranteed to be up-to-date at every node at all times. Data is in flux while replicas synchronise.
  • E — Eventually Consistent: All replicas will converge to the same value — but not instantly. Given no new writes, the system will reach agreement eventually.

The name "BASE" was coined as a deliberate contrast to "ACID" in chemistry: acids are sharp and precise; bases are more flexible and tolerant.

DimensionACIDBASE
Consistency modelStrong, immediateEventual
Availability during partitionMay block or rejectAlways responds
State guaranteeAlways validValid eventually
Typical settingRelational databasesDistributed NoSQL systems
Core trade-offCorrectness over availabilityAvailability over correctness

🔢 ACID Refresher: The Four Promises of Relational Databases

PropertyMeaningExample
AtomicityAll-or-nothing. Either all operations in a transaction commit, or none do.Bank transfer: debit and credit both succeed or both roll back.
ConsistencyThe database always moves from one valid state to another — no constraint violations.A column with NOT NULL constraint is never left empty.
IsolationConcurrent transactions behave as if they ran sequentially.Two users booking the last seat cannot both see it as available.
DurabilityOnce committed, data survives crashes.A PostgreSQL commit is written to the WAL before acknowledging.

⚙️ BASE in Detail: The Three Properties Unpacked

B — Basically Available

The system returns a response to every request, even if that response is stale or partial. Think of Amazon showing a product as "In Stock" based on the last known count, even if the live count hasn't propagated yet.

S — Soft State

The state of the system may change over time even without new input, as consistency information propagates across nodes. The data is "in flux" during the window between a write and full propagation.

E — Eventually Consistent

Given no new updates, the system will converge — eventually — to a consistent state across all replicas. The key word is eventually: it might be milliseconds, it might be seconds, but not guaranteed to be instant.

flowchart LR
    Client --> NodeA[Node A\nWrite X=5]
    NodeA --> NodeB[Node B\nX=5 propagates]
    NodeA --> NodeC[Node C\nX=5 propagates]
    NodeC --> StaleRead[Stale read\nX=3 for ~100ms]
    NodeB --> FreshRead[Fresh read\nX=5]

📊 Write Flow: ACID vs BASE

The difference between ACID and BASE becomes clearest when you trace a single write through each system. In an ACID system, a write must acquire locks, coordinate with all replicas, and only acknowledge success after every node confirms. In a BASE system, a write is accepted locally and immediately acknowledged — replica propagation happens asynchronously in the background.

flowchart LR
    subgraph ACID ["ACID (e.g. PostgreSQL)"]
        W1[Write] --> Lock[Acquire Lock]
        Lock --> Commit[Commit to All Replicas]
        Commit --> Ack1[✅ Acknowledged]
    end
    subgraph BASE ["BASE (e.g. Cassandra)"]
        W2[Write] --> Local[Write to Local Node]
        Local --> Ack2[✅ Immediately Acknowledged]
        Ack2 --> Prop[Propagate to Replicas\nasynchronously]
    end

The ACID path is slower but guarantees every reader immediately sees the committed value. The BASE path is faster but leaves a window — potentially milliseconds to seconds — where different nodes return different values for the same key.


🧠 Deep Dive: Eventual Consistency and the Shopping Cart

Amazon's Dynamo paper (2007) used the shopping cart as the canonical example.

  • You add "Red Shoes" to your cart on your phone.
  • You open your cart on your laptop 200 ms later.
  • The write hasn't propagated yet — the laptop sees the old cart (no Red Shoes).
  • After ~500 ms, both devices show "Red Shoes."

The system chose availability (always respond) over strong consistency (always latest value). For a shopping cart, a brief stale view is acceptable. For a bank balance, it is not.


⚖️ Trade-offs & Failure Modes: ACID vs BASE

DimensionACIDBASE
ConsistencyStrong, immediateEventual
AvailabilityCan reject requests during partitionAlways responds
Write throughputLimited by lock and quorum overheadHigh — local writes accepted immediately
Typical databasesPostgreSQL, MySQL, CockroachDBDynamoDB, Cassandra, MongoDB (tunable)
Best forFinance, inventory, bookingsSocial feeds, caches, shopping carts, analytics

Decision rule of thumb: If your data has money, seats, or contracts in it, lean toward ACID. If your data has likes, views, or preferences in it, BASE is usually fine.


🧪 Picking the Right Model: Real Scenarios and Decision Signals

Knowing the theory is one thing — recognising which model fits a given feature is where the real skill lies. Here is a practical decision framework with concrete examples:

Use ACID when:

ScenarioWhy ACIDExample system
Bank transfer or paymentPartial completion = money lostPostgreSQL, CockroachDB
Seat reservation / ticketingDouble-booking is unacceptableMySQL with row locks
Inventory deduction at checkoutNegative stock must be impossibleTransactional SQL
User account creationUnique constraint must always holdAny RDBMS

Use BASE when:

ScenarioWhy BASEExample system
Social media feedStale post for 100ms is fineCassandra, DynamoDB
User preference or settingsLast-write-wins is acceptableRedis, DynamoDB
DNS record lookupGlobal propagation delay expectedDNS (inherently BASE)
Leaderboard / view counterApproximate count is fineRedis Sorted Sets
Product catalogue browsingBrief cache lag acceptableCDN + cache-aside Redis

The grey zone — when you need both: Some systems need ACID for the critical path and BASE everywhere else. An e-commerce checkout flow might use ACID for inventory and payment, but BASE for displaying product reviews or wish-list items. Modern databases like DynamoDB (with transactions) and Cassandra (with QUORUM consistency) let you dial in per-operation consistency requirements, giving you the best of both worlds where it matters.


🌍 Real-World Applications: BASE Systems in the Wild

  • Amazon DynamoDB: Eventual consistency by default; strongly consistent reads available with extra cost.
  • Apache Cassandra: Tunable consistency — you choose per-query: ONE, QUORUM, or ALL.
  • Redis (cache-aside): Classic soft-state — your cache is always slightly behind the source of truth.
  • DNS: The most widely used eventually consistent system on earth. A domain change can take up to 48 hours to propagate globally.

🧭 Decision Guide: ACID or BASE?

Choose your consistency model at design time — not after the first data-loss incident.

Use CaseModelWhy
Bank transfer, bookings, inventoryACIDPartial updates cause financial loss or over-commitment
Social feed, analytics, countersBASE with mergeOccasional stale view is fine; conflicts merged on checkout
Shopping cart, preferencesBASE with mergeOccasional stale view is fine; conflicts merged on checkout
User sessions, access tokensLean ACIDRevoked tokens must never appear as valid
DNS, CDN cache, leaderboardBASEGlobal scale; seconds of staleness is expected and fine

A hybrid is normal: use an RDBMS for the critical ACID path and DynamoDB or Redis for everything that can tolerate eventual consistency.

📊 ACID Transaction Sequence

sequenceDiagram
    participant C as Client
    participant DB as Database

    C->>DB: BEGIN TRANSACTION
    C->>DB: READ balance (1000)
    C->>DB: VALIDATE (balance >= 200)
    C->>DB: WRITE balance = 800
    C->>DB: COMMIT
    DB-->>C: OK (durable, all-or-nothing)
    Note over DB: Rollback if any step fails

📊 BASE Eventual Consistency Sequence

sequenceDiagram
    participant C as Client
    participant A as Node A (primary)
    participant B as Node B (replica)

    C->>A: Write X = 5
    A-->>C: OK (local ack)
    Note over B: X still = 3 (stale)
    A->>B: async replicate X = 5
    Note over B: ~100ms later: X = 5 (converged)

📊 ACID vs BASE: Selection Decision Tree

flowchart TD
    A[New data requirement] --> B{Partial failure tolerable?}
    B -- No --> C{Need atomic multi-row writes?}
    C -- Yes --> D[ACID — RDBMS with transactions]
    C -- No --> E[ACID — single-row with constraints]
    B -- Yes --> F{Global scale or high availability?}
    F -- Yes --> G[BASE — NoSQL e.g. Cassandra DynamoDB]
    F -- No --> H{Reads outnumber writes 10x+?}
    H -- Yes --> I[BASE — eventual consistency + cache]
    H -- No --> D

📚 Lessons That Bite: Where BASE Goes Wrong (and How to Avoid It)

BASE is not simply a relaxed version of ACID — it comes with its own failure modes that catch engineers off-guard the first time they operate an eventually consistent system.

Lesson 1 — CAP theorem is the root cause, not a buzzword. The ACID vs BASE split ultimately comes from the CAP theorem: during a network partition, a distributed system must choose between remaining consistent (ACID) or remaining available (BASE). Understanding this removes the mystery: BASE is not laziness, it is a deliberate architectural response to partition tolerance.

Lesson 2 — Tunable consistency is your safety dial. Databases like Cassandra expose a consistency dial. ONE means accept from any single replica (maximum availability, minimum consistency). QUORUM means require a majority (balanced). ALL means require every replica (maximum consistency, minimum availability). Always consciously choose the right level per operation — defaulting to ONE everywhere is a latent bug waiting for a failure scenario.

Lesson 3 — BASE bites hardest during write conflicts. If two clients write different values to the same key before propagation completes, BASE systems resolve the conflict with rules like "last write wins" (by timestamp) or "merge" (CRDTs). Last-write-wins silently discards one user's update. If that update was a medical record, a legal document, or an account balance, the data loss is invisible and catastrophic. Audit your write conflict resolution strategy before shipping.

Lesson 4 — Hybrid architectures are normal and expected. Very few production systems are purely ACID or purely BASE. A real-world service might write payments to PostgreSQL, cache product listings in Redis, store user activity in Cassandra, and queue async jobs in a BASE-friendly message broker. Designing the boundary between the ACID and BASE zones is one of the most important system design decisions you will make.


📌 TLDR: Summary & Key Takeaways

  • BASE is the design philosophy behind highly available, horizontally scalable systems.
  • Basically Available: always respond, even if data is stale.
  • Soft State: data is in flux during propagation; eventual consistency is the target.
  • Eventually Consistent: all replicas converge, just not instantly.
  • Choose ACID for money, seats, or contracts; choose BASE for social, caching, or analytics.

📝 Practice Quiz

  1. What does the "A" in ACID stand for, and what does it guarantee?

    • A) Availability — the system always responds
    • B) Atomicity — all operations in a transaction succeed or none do
    • C) Accuracy — the database never stores incorrect data
    • D) Asynchrony — writes happen without waiting for a reply Correct Answer: B — Atomicity means a transaction is all-or-nothing. If any step fails, the entire transaction is rolled back.
  2. A user updates their profile photo on their phone. A friend refreshes their browser 200 ms later and still sees the old photo. Which BASE property explains this?

    • A) Basically Available — the system returned a response to the friend
    • B) Soft State — data is still propagating; the system state is in flux
    • C) Eventually Consistent — replicas have not yet converged on the new photo
    • D) Both B and C are correct Correct Answer: D — Soft State describes that data is in transition, and Eventually Consistent describes that all replicas will eventually agree. Both apply simultaneously during the propagation window.
  3. You are designing a flight seat reservation system. A seat must never be double-booked. Which consistency model should you choose?

    • A) BASE with eventual consistency and last-write-wins conflict resolution
    • B) ACID with strict isolation so two bookings cannot both see the seat as available
    • C) BASE with tunable consistency set to ONE for maximum availability
    • D) No consistency model is needed; the application layer can handle duplicates Correct Answer: B — Double-booking is a classic isolation problem. ACID's isolation guarantee ensures two concurrent transactions cannot both read the seat as free and commit a booking.

🛠️ Spring Data + Apache Kafka: @Transactional for ACID, Events for BASE

Spring Data is the persistence abstraction in the Spring ecosystem, providing @Transactional, JpaRepository, and CrudRepository to deliver ACID semantics over relational databases. Apache Kafka is the distributed event streaming platform most commonly used alongside Spring to implement the BASE side — a confirmed write propagates to other services asynchronously via events, achieving eventual consistency without distributed transactions.

ACID path — Spring @Transactional ensures atomicity across inventory and order writes:

@Service
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository     orderRepository;      // JPA → PostgreSQL
    private final InventoryRepository inventoryRepository;
    private final KafkaTemplate<String, OrderEvent> kafka;

    @Transactional   // ← ACID: both DB writes succeed or both roll back atomically
    public Order placeOrder(OrderRequest request) {

        // Step 1 — Debit inventory (constraint: stock must not go negative)
        Inventory inv = inventoryRepository
            .findByProductIdWithLock(request.getProductId());   // SELECT FOR UPDATE

        if (inv.getStock() < request.getQuantity()) {
            throw new InsufficientStockException("Product out of stock");
        }
        inv.setStock(inv.getStock() - request.getQuantity());
        inventoryRepository.save(inv);

        // Step 2 — Create order record in the same transaction
        Order order = new Order(
            UUID.randomUUID().toString(),
            request.getUserId(),
            request.getProductId(),
            request.getQuantity(),
            OrderStatus.CONFIRMED
        );
        return orderRepository.save(order);

        // If any step above throws a RuntimeException,
        // @Transactional rolls back BOTH writes — no partial state possible
    }
}

BASE path — Kafka event decouples downstream services from the critical transaction:

    @Transactional
    public Order placeOrder(OrderRequest request) {
        Order saved = placeOrderInternal(request);   // ACID writes above

        // Publish event AFTER the transaction commits successfully
        // Downstream consumers (notification, analytics, warehouse) process asynchronously
        kafka.send("order-events",
            saved.getId(),
            new OrderEvent(saved.getId(), saved.getUserId(), OrderEventType.PLACED)
        );
        return saved;
        // Important: the Kafka send is NOT inside the DB transaction.
        // Use the Outbox Pattern (write event to a DB table in the same transaction,
        // then relay to Kafka asynchronously) for guaranteed exactly-once delivery.
    }

Kafka consumer — BASE eventual consistency on the notification service side:

@Service
public class NotificationConsumer {

    @KafkaListener(topics = "order-events", groupId = "notification-service")
    public void handleOrderPlaced(OrderEvent event) {
        if (event.getType() == OrderEventType.PLACED) {
            // This runs asynchronously — may be milliseconds or seconds after the order commit
            // This is the BASE property: Eventually Consistent delivery
            notificationService.sendConfirmation(event.getUserId(), event.getOrderId());
        }
    }
}

The ACID boundary is the PostgreSQL transaction (inventory + order). The Kafka event is BASE: the notification service is eventually consistent — it will process the event, but not within the same atomic boundary. The Outbox Pattern closes the delivery gap when exactly-once semantics are required.

For a full deep-dive on Spring Data transactions, the Outbox Pattern with Debezium CDC, and Kafka exactly-once semantics in Spring Boot, a dedicated follow-up post is planned.


Abstract Algorithms

Written by

Abstract Algorithms

@abstractalgorithms