How Write-Behind Works
How Write-Behind Works
Write-Behind (also called Write-Back) writes to cache immediately and asynchronously persists to the database.
Flow Diagram
Write-Behind Flow:
App → Write to Cache → Return Success (immediate)
↓
[Background] → Batch write to DB
Fast writes, eventual persistence!
Implementation
class WriteBehindCache:
def __init__(self, cache_client, db_client):
self.cache = cache_client
self.db = db_client
self.write_queue = Queue()
self.start_background_writer()
def set(self, key, value, ttl=3600):
"""Write-behind: write to cache immediately, queue DB write"""
# Write to cache (fast)
self.cache.set(key, value, ttl)
# Queue database write (async)
self.write_queue.put({'key': key, 'value': value})
return True # Return immediately
def start_background_writer(self):
"""Background thread to persist queued writes"""
def writer():
while True:
batch = []
# Collect batch of writes
while not self.write_queue.empty() and len(batch) < 100:
batch.append(self.write_queue.get())
if batch:
# Batch write to database
self.db.batch_upsert(batch)
time.sleep(0.1) # Small delay between batches
thread = threading.Thread(target=writer, daemon=True)
thread.start()
Characteristics
- Immediate cache write (fast response)
- Async database persistence
- Batch writes for efficiency
- Eventual consistency with database
Async Persistence
Async Persistence in Write-Behind
Persistence Strategies
Strategy Options:
1. Immediate Async:
Write to cache → Queue for immediate DB write
Pros: Low latency, simple
Cons: Many small DB writes
2. Batched Async:
Write to cache → Batch queue → Periodic DB write
Pros: Efficient DB writes
Cons: More data at risk
3. Time-Based Flush:
Write to cache → Flush every N seconds
Pros: Predictable DB load
Cons: Fixed interval may not be optimal
Batch Implementation
class BatchedWriteBehind:
def __init__(self, cache, db, batch_size=100, flush_interval=1.0):
self.cache = cache
self.db = db
self.batch_size = batch_size
self.flush_interval = flush_interval
self.buffer = []
self.lock = threading.Lock()
def set(self, key, value, ttl=3600):
# Immediate cache write
self.cache.set(key, value, ttl)
# Buffer for batch DB write
with self.lock:
self.buffer.append({'key': key, 'value': value})
if len(self.buffer) >= self.batch_size:
self.flush()
def flush(self):
"""Flush buffer to database"""
with self.lock:
if self.buffer:
self.db.batch_upsert(self.buffer)
self.buffer = []
Durability Considerations
- WAL (Write-Ahead Log): Persist to disk before acknowledging
- Replication: Replicate cache to multiple nodes
- Checkpointing: Periodic full snapshots to DB
- Recovery: Rebuild cache from DB on failure
Risk Management
Risk Management in Write-Behind
Data Loss Scenarios
Risk Analysis:
1. Cache Failure:
- Risk: Unpersisted writes lost
- Mitigation: WAL, replication, short flush intervals
2. DB Failure:
- Risk: Writes pile up in queue
- Mitigation: Overflow to disk, circuit breaker
3. Process Crash:
- Risk: In-memory buffer lost
- Mitigation: Persistent queue, WAL
4. Network Partition:
- Risk: Can't reach DB
- Mitigation: Local persistence, retry with backoff
Safety Implementation
class SafeWriteBehind:
def __init__(self, cache, db, wal_path='/data/wal'):
self.cache = cache
self.db = db
self.wal = WriteAheadLog(wal_path)
def set(self, key, value, ttl=3600):
# 1. Write to WAL first (durability)
self.wal.append({'op': 'set', 'key': key, 'value': value})
# 2. Write to cache (performance)
self.cache.set(key, value, ttl)
# 3. Queue DB write (async)
self.queue.put({'key': key, 'value': value})
def recover(self):
"""Recover from WAL after crash"""
pending = self.wal.replay()
for entry in pending:
self.cache.set(entry['key'], entry['value'])
self.queue.put(entry)
When to Use Write-Behind
Good for:
- High write throughput requirements
- Write-heavy workloads
- When slight data loss is acceptable
- Analytics and logging
- Session storage
Not ideal for:
- Financial transactions
- Critical data requiring strong consistency
- Low-latency write requirements
- Systems that can't tolerate data loss
Practice Problems
Design a scalable Write-Behind system. Cover high-level architecture, data model, and API design.
Solution
// Complete system design:
// - Functional + Non-functional requirements
// - Capacity estimation
// - Data model (SQL/NoSQL choice)
// - API endpoints
// - Component architecture
// - Scaling strategy
// - Monitoring & reliabilityHow would you scale Write-Behind to handle 10x the current load? Identify bottlenecks and solutions.
Solution
// Scaling approach:
// 1. Load balancing
// 2. Database sharding/replication
// 3. Cache layer (Redis)
// 4. CDN for static assets
// 5. Async processing (queues)
// 6. Microservices decompositionAnalyze potential failure modes for Write-Behind and design mitigation strategies.
Solution
// Failure mitigation:
// 1. Redundancy (multi-AZ)
// 2. Circuit breakers
// 3. Retry with backoff
// 4. Dead letter queues
// 5. Health checks
// 6. Graceful degradationQuiz
1. In Write-Behind, when is the database updated?
2. What is the main risk of Write-Behind?
3. How does batching help Write-Behind?
4. What is a WAL (Write-Ahead Log) used for in Write-Behind?
5. When should you NOT use Write-Behind?
Flashcards
Question
What is Write-Behind caching?
Click to reveal answer
Answer
A pattern where data is written to cache immediately and persisted to database asynchronously in the background
Question
What is the main risk of Write-Behind?
Click to reveal answer
Answer
Data loss if cache fails before database persistence - mitigated by WAL and replication
Question
Why batch writes in Write-Behind?
Click to reveal answer
Answer
Batching reduces database round trips and improves throughput by grouping multiple writes into single operations
Question
What does WAL stand for and why use it?
Click to reveal answer
Answer
Write-Ahead Log - persists writes to disk before cache write to ensure durability and enable crash recovery
Question
Best use cases for Write-Behind?
Click to reveal answer
Answer
High write throughput, analytics, logging, session storage - where eventual consistency is acceptable
Revision Notes
Key Takeaways
- 1.Write-Behind provides fast writes by only writing to cache synchronously
- 2.Main risk: data loss if cache fails before DB persistence
- 3.Use WAL (Write-Ahead Log) for durability protection
- 4.Batch writes improve database efficiency
- 5.Not suitable for data requiring strong consistency
Interview Tips
- •Clearly explain the async nature and trade-offs
- •Discuss data loss scenarios and mitigations (WAL, replication)
- •Compare with Write-Through: speed vs consistency trade-off
- •Mention batching as a key optimization technique
Cheat Sheet
Cheat Sheet: Write-Behind
Flow
App → Cache Write → Return (immediate) → [Async] → DB Write
Key Points
- Fast writes (cache only)
- Eventual consistency
- Risk of data loss
- Use WAL for durability
- Batch writes for efficiency
Risk Mitigation
- Write-Ahead Log (WAL)
- Cache replication
- Short flush intervals
- Overflow to disk
When to Use
- High write throughput
- Eventual consistency OK
- Analytics/logging
- NOT for financial data