Interview Essential: These fundamentals are the building blocks of every system design. Interviewers expect you to naturally incorporate these concepts without being asked.
Reads might return stale data, but eventually all nodes will have the same data.
Copy
# Python: Eventual Consistency with Async Replicationimport asynciofrom datetime import datetimeclass EventualConsistencyDB: def __init__(self, replicas: list): self.replicas = replicas self.replication_queue = asyncio.Queue() async def write(self, key: str, value: any) -> bool: """Write to local node immediately, replicate asynchronously""" # Write to local node (fast!) timestamp = datetime.utcnow() self.local_node.write(key, value, timestamp) # Queue async replication (non-blocking) await self.replication_queue.put({ 'key': key, 'value': value, 'timestamp': timestamp }) return True # Returns immediately! async def replicate_worker(self): """Background worker that replicates to other nodes""" while True: item = await self.replication_queue.get() for replica in self.replicas: try: await replica.async_write( item['key'], item['value'], item['timestamp'] ) except Exception as e: # Retry later (eventual consistency) await self.retry_queue.put(item) async def read(self, key: str) -> any: """Read from local node (might be stale!)""" return self.local_node.read(key)# Usage in social mediadb = EventualConsistencyDB(replicas=[node1, node2, node3])await db.write("post:456", {"content": "Hello World!"})# User might not see this post immediately on other nodes# But eventually (usually within milliseconds), all nodes will have it
Copy
// JavaScript: Eventual Consistency with Async Replicationclass EventualConsistencyDB { constructor(replicas) { this.replicas = replicas; this.replicationQueue = []; this.startReplicationWorker(); } async write(key, value) { const timestamp = Date.now(); // Write to local node immediately await this.localNode.write(key, value, timestamp); // Queue for async replication (fire and forget) this.replicationQueue.push({ key, value, timestamp }); return true; // Returns immediately! } startReplicationWorker() { setInterval(async () => { while (this.replicationQueue.length > 0) { const item = this.replicationQueue.shift(); // Replicate to all nodes in background for (const replica of this.replicas) { try { await replica.asyncWrite(item.key, item.value, item.timestamp); } catch (error) { // Put back in queue for retry this.replicationQueue.push(item); } } } }, 100); // Process every 100ms } async read(key) { // Read from local (might be stale) return await this.localNode.read(key); }}
Users always see their own writes immediately, even if other users see stale data.
Copy
# Python: Read-Your-Writes with Session Trackingfrom datetime import datetime, timedeltaclass ReadYourWritesDB: def __init__(self, primary, replicas): self.primary = primary self.replicas = replicas self.user_last_write = {} # Track when each user last wrote def write(self, user_id: str, key: str, value: any) -> bool: """Write to primary and track the write timestamp""" timestamp = datetime.utcnow() self.primary.write(key, value, timestamp) # Remember when this user last wrote self.user_last_write[user_id] = timestamp # Async replication to replicas self.async_replicate(key, value, timestamp) return True def read(self, user_id: str, key: str) -> any: """ If user recently wrote, read from primary. Otherwise, read from replica (faster). """ last_write = self.user_last_write.get(user_id) # If user wrote in last 5 seconds, use primary if last_write and (datetime.utcnow() - last_write) < timedelta(seconds=5): return self.primary.read(key) # Safe to read from replica (user hasn't written recently) return self.get_random_replica().read(key)# Usagedb = ReadYourWritesDB(primary, [replica1, replica2])db.write("user_123", "profile:user_123", {"name": "Alice"})profile = db.read("user_123", "profile:user_123") # Reads from PRIMARYprofile = db.read("user_456", "profile:user_123") # Reads from REPLICA
Copy
// JavaScript: Read-Your-Writes Consistencyclass ReadYourWritesDB { constructor(primary, replicas) { this.primary = primary; this.replicas = replicas; this.userLastWrite = new Map(); // userId -> timestamp } async write(userId, key, value) { const timestamp = Date.now(); // Write to primary await this.primary.write(key, value, timestamp); // Track when user last wrote this.userLastWrite.set(userId, timestamp); // Async replication (fire and forget) this.asyncReplicate(key, value, timestamp); return true; } async read(userId, key) { const lastWrite = this.userLastWrite.get(userId); const fiveSecondsAgo = Date.now() - 5000; // If user wrote recently, read from primary if (lastWrite && lastWrite > fiveSecondsAgo) { return await this.primary.read(key); } // Otherwise, read from any replica (faster) const replica = this.replicas[Math.floor(Math.random() * this.replicas.length)]; return await replica.read(key); }}// User always sees their own updates immediatelyconst db = new ReadYourWritesDB(primary, [replica1, replica2]);await db.write('user_123', 'profile:user_123', { name: 'Alice' });const myProfile = await db.read('user_123', 'profile:user_123'); // From PRIMARYconst theirProfile = await db.read('user_456', 'profile:user_123'); // From REPLICA
Leader election: Only one leader should exist at a time
Key phrase: “In this case, returning wrong data is worse than returning no data.”
How do you achieve 99.99% availability?
Answer: Redundancy at every layer:
Multiple DNS providers
CDN with many edge locations
Load balancers in active-passive or active-active mode
Multiple application servers (stateless)
Database replication (primary + replicas)
Multi-region deployment
Health checks and automatic failover
Circuit breakers to prevent cascade failures
Explain eventual consistency with an example
Answer: “When you post on social media, your friend might not see it for a few seconds because the data needs to propagate across replicas. This is acceptable because:
Availability is more important than instant consistency
The delay is usually sub-second and imperceptible
The data will eventually be consistent everywhere
Compare to a bank transfer where you MUST see accurate balance immediately - that needs strong consistency.”
How do you estimate QPS quickly?
Answer: Use the “divide by 100,000” rule:
DAU × requests per day ÷ 100,000 ≈ QPS
Example: 100M DAU × 10 requests = 1B / 100,000 = 10,000 QPS