ACID vs BASE — Deep Dive
Level: Intermediate
Pre-reading: 01 · Architectural Foundations · 01.03 · CAP Theorem
Two Models of Data Consistency
Distributed systems force a choice between two consistency models. ACID prioritizes correctness and strong guarantees. BASE prioritizes availability and performance, accepting eventual consistency.
| ACID | BASE | |
|---|---|---|
| Philosophy | Pessimistic; prevent all anomalies | Optimistic; accept temporary inconsistency |
| Consistency | Strong; immediate | Eventual; converges over time |
| Availability | May block or reject | Always available |
| Use case | Financial systems, inventory | Social feeds, analytics, caches |
ACID — The Traditional Model
ACID transactions guarantee four properties:
Atomicity — All or Nothing
A transaction either completes entirely or has no effect. If any part fails, all changes are rolled back.
sequenceDiagram
participant App
participant DB
App->>DB: BEGIN TRANSACTION
App->>DB: UPDATE accounts SET balance = balance - 100 WHERE id = 1
App->>DB: UPDATE accounts SET balance = balance + 100 WHERE id = 2
Note over DB: Power failure here
DB->>DB: ROLLBACK (both updates undone)
| Without Atomicity | With Atomicity |
|---|---|
| Money debited from A, but credit to B lost | Either both happen or neither happens |
| Inconsistent state persisted | System always in valid state |
Consistency — Valid State Transitions
The database moves from one valid state to another. Constraints (foreign keys, check constraints, triggers) are enforced. Invariants are preserved.
Consistency in ACID vs CAP
These are different concepts. ACID consistency = database invariants preserved. CAP consistency = all nodes see the same data at the same time.
Isolation — Concurrent Transactions Don't Interfere
Transactions execute as if they were serial, even when running concurrently.
| Isolation Level | Dirty Read | Non-Repeatable Read | Phantom Read | Performance |
|---|---|---|---|---|
| Read Uncommitted | ✗ Possible | ✗ Possible | ✗ Possible | Fastest |
| Read Committed | ✓ Prevented | ✗ Possible | ✗ Possible | Fast |
| Repeatable Read | ✓ Prevented | ✓ Prevented | ✗ Possible | Medium |
| Serializable | ✓ Prevented | ✓ Prevented | ✓ Prevented | Slowest |
sequenceDiagram
participant T1 as Transaction 1
participant DB
participant T2 as Transaction 2
T1->>DB: SELECT balance WHERE id=1 (returns 100)
T2->>DB: UPDATE balance = 50 WHERE id=1
T2->>DB: COMMIT
T1->>DB: SELECT balance WHERE id=1
Note over T1,DB: Non-repeatable read: 50 ≠ 100
Durability — Committed Data Survives Failures
Once a transaction commits, its changes persist even if the system crashes immediately after.
| Mechanism | Description |
|---|---|
| Write-Ahead Log (WAL) | Changes logged before applied; replay on recovery |
| Fsync | Force write to disk (not just OS buffer) |
| Replication | Synchronous replication to standby |
| Checksums | Detect corruption on read |
ACID Implementation Techniques
Two-Phase Locking (2PL)
| Phase | Behavior |
|---|---|
| Growing phase | Transaction acquires locks; cannot release any |
| Shrinking phase | Transaction releases locks; cannot acquire new |
Guarantees serializability but can cause deadlocks.
Multi-Version Concurrency Control (MVCC)
Instead of locking, each transaction sees a snapshot of the database at a point in time. Writers create new versions; readers see old versions.
graph LR
subgraph Row Versions
V1[Version 1 - created T1]
V2[Version 2 - created T5]
V3[Version 3 - created T10]
end
T3[Transaction 3] -.->|Sees| V1
T7[Transaction 7] -.->|Sees| V2
T12[Transaction 12] -.->|Sees| V3
| Database | Concurrency Control |
|---|---|
| PostgreSQL | MVCC (snapshot isolation) |
| MySQL InnoDB | MVCC + row locks |
| Oracle | MVCC |
| SQL Server | 2PL by default; MVCC optional |
BASE — The Distributed Model
BASE is the alternative for systems where ACID's guarantees are too expensive:
Basically Available
The system guarantees availability, even during partial failures. Some requests may get degraded responses, but the system doesn't go offline.
Soft State
The system's state may change over time, even without input, due to eventual consistency. Data may be temporarily inconsistent between replicas.
Eventually Consistent
If no new updates are made, all replicas will eventually converge to the same value. The "eventually" may be milliseconds or seconds.
sequenceDiagram
participant Client
participant Node1
participant Node2
participant Node3
Client->>Node1: Write X=5
Node1->>Node1: X=5
Node1-->>Node2: Async replicate
Node1-->>Node3: Async replicate
Note over Node1,Node3: Brief inconsistency window
Node2->>Node2: X=5
Node3->>Node3: X=5
Note over Node1,Node3: Eventually consistent
Eventual Consistency — Deeper Look
Types of Eventual Consistency
| Type | Guarantee |
|---|---|
| Eventual | All replicas converge given enough time |
| Read-your-writes | Client always sees their own writes |
| Monotonic reads | Client never sees older data after seeing newer |
| Monotonic writes | Client's writes are serialized in order |
| Causal | Causally related operations seen in order |
The Consistency Window
The time between when a write occurs and when all replicas reflect it.
| Factor | Effect on Window |
|---|---|
| Network latency | Higher latency → longer window |
| Replication lag | More replicas → longer to propagate |
| Write volume | Higher volume → replication falls behind |
| Conflict resolution | Complex resolution → longer convergence |
Comparing ACID and BASE
| Aspect | ACID | BASE |
|---|---|---|
| Focus | Correctness | Availability |
| Scale | Single node or distributed with coordination | Massively distributed |
| Performance | Bounded by coordination | High throughput |
| Failure mode | Reject operations | Accept and reconcile |
| Complexity | In the database | In the application |
| Use case | Banking, inventory | Social, analytics, cache |
When to Choose ACID
| Scenario | Rationale |
|---|---|
| Money transfers | Cannot have inconsistent balances |
| Inventory decrement | Must prevent overselling |
| Booking systems | Cannot double-book resources |
| Audit requirements | Need provable transaction history |
When to Choose BASE
| Scenario | Rationale |
|---|---|
| Social media likes | Approximate counts acceptable |
| Shopping cart | Merge conflicts on sync |
| Product recommendations | Stale data is acceptable |
| Metrics/analytics | Eventual accuracy is fine |
Distributed Transactions — ACID Across Services
When ACID guarantees are needed across multiple services:
Two-Phase Commit (2PC)
sequenceDiagram
participant C as Coordinator
participant P1 as Participant 1
participant P2 as Participant 2
Note over C,P2: Phase 1 - Prepare
C->>P1: Prepare
C->>P2: Prepare
P1->>C: Vote YES
P2->>C: Vote YES
Note over C,P2: Phase 2 - Commit
C->>P1: Commit
C->>P2: Commit
P1->>C: ACK
P2->>C: ACK
| Problem | Description |
|---|---|
| Blocking | Participants hold locks until coordinator decides |
| Coordinator failure | Participants stuck in prepared state |
| Latency | Multiple round-trips |
| Availability | Any participant failure blocks all |
Avoid 2PC in microservices
2PC creates tight coupling and availability problems. Use Saga pattern with compensating transactions instead.
Saga Pattern — BASE for Cross-Service Transactions
Each step is a local ACID transaction. On failure, execute compensating transactions to undo previous steps.
→ Deep Dive: Saga Pattern for choreography vs orchestration, compensating transactions
Hybrid Approaches
Strong Consistency for Writes, Eventual for Reads
graph LR
W[Write] --> P[(Primary - Strong)]
P -->|Async| R1[(Read Replica)]
P -->|Async| R2[(Read Replica)]
RD[Read] --> R1
RD --> R2
| Operation | Consistency | Target |
|---|---|---|
| Create Order | Strong | Primary database |
| View Order List | Eventual | Read replica |
| Update Inventory | Strong | Primary database |
| Browse Products | Eventual | Read replica or cache |
Consistency Per Operation
Many databases allow tuning consistency per query:
-- DynamoDB: strongly consistent read
aws dynamodb get-item --consistent-read
-- Cassandra: quorum consistency
SELECT * FROM orders WHERE id = 123 CONSISTENCY QUORUM;
Application-Level Consistency Patterns
When the database doesn't guarantee consistency, the application must:
| Pattern | Implementation |
|---|---|
| Idempotency keys | Store operation ID; reject duplicates |
| Optimistic locking | Version column; reject stale updates |
| Conflict-free data types | CRDTs that merge automatically |
| Event sourcing | Append-only events; derive state |
| Compensating actions | Undo on failure |
What's the difference between consistency in ACID vs consistency in CAP?
ACID consistency means database invariants are preserved — constraints are enforced, referential integrity maintained. It's about valid state transitions within a single database. CAP consistency means all nodes in a distributed system see the same data at the same time — it's about replica synchronization. A system can be ACID-consistent on each node but CAP-inconsistent across nodes.
Why is 2PC problematic for microservices?
(1) Blocking: All participants hold locks waiting for coordinator decision. (2) Single point of failure: Coordinator failure leaves participants stuck. (3) Tight coupling: All services must participate in the protocol. (4) Availability: Any participant being unavailable blocks the entire transaction. (5) Latency: Multiple synchronous round-trips. Use Saga pattern instead — local transactions with compensating actions.
How do you handle eventual consistency in a user-facing application?
(1) Optimistic UI: Show the expected state immediately; reconcile if different. (2) Read-your-writes: Route reads to the node that handled the write. (3) Polling/websockets: Update UI when data converges. (4) Explicit messaging: "Your order is being processed" instead of showing stale state. (5) Idempotent retries: Safe to retry if user refreshes during consistency window.