A payment API receives duplicate POST /charge requests because the client retries on a 504 gateway timeout. Charges must never be double-applied. The request carries a client-generated `Idempotency-Key`. Which server implementation actually guarantees exactly-once effect under concurrent retries?
- A. On each request, SELECT the key; if absent, process the charge and then INSERT the key with the result
- B. Wrap the charge in a transaction and rely on the DB's default READ COMMITTED isolation to serialize the two requests
- C. INSERT the idempotency key with a UNIQUE constraint FIRST in the same transaction as the charge; on duplicate-key violation, return the stored prior response ✓
- D. Hash the request body and skip processing if an identical body was seen in the last 60 seconds
Correct answer: C. Inserting the unique key first makes the database's uniqueness constraint the concurrency gate, so exactly one transaction commits the charge and retries hit the duplicate-key path, whereas check-then-act (option 0) has a race window between SELECT and INSERT.
A hot cache key holding a homepage product list expires. Within milliseconds thousands of concurrent requests miss and all hit the database, which collapses. Besides the immediate outage, which mitigation prevents recurrence WITHOUT weakening correctness the way plain 'never expire' would?
- A. Increase the connection pool size so the database can absorb the simultaneous rebuild queries
- B. Use a per-key distributed lock/single-flight so only one request rebuilds the value while others briefly wait or serve the stale value ✓
- C. Switch the cache eviction policy from LRU to LFU so hot keys are evicted less often
- D. Shorten the TTL so the key refreshes more frequently and is never deeply stale
Correct answer: B. Single-flight (mutex/lease per key) collapses the stampede to a single database rebuild while other callers wait or serve stale, directly eliminating the thundering herd; a bigger pool just lets more queries pile on and a shorter TTL makes stampedes more frequent.
Two transactions run concurrently under a database using MVCC snapshot isolation (e.g. Postgres REPEATABLE READ). Both read the current seat count (0 booked of 1), both see a seat available, and both INSERT a booking. What actually happens, and why is this the classic gap in snapshot isolation?
- A. One INSERT blocks until the other commits, then sees the updated count and aborts itself
- B. Both commit successfully; snapshot isolation does not detect this write-skew because the two writes touch different rows than the ones read ✓
- C. The second commit fails automatically with a serialization error because MVCC guarantees serializability
- D. Both are rolled back because a phantom row was inserted by a concurrent transaction
Correct answer: B. This is write skew: each transaction reads a snapshot and writes rows the other did not read, so snapshot isolation (short of true SERIALIZABLE / SSI) allows both to commit, violating the invariant, which is why you need SELECT ... FOR UPDATE, a serializable level, or a materialized conflict row.
A Kafka consumer group processes orders. Each poll returns a batch of 500; the consumer commits offsets AFTER the whole batch is processed. A consumer instance crashes after processing 300 of 500 records but before committing. Assuming default at-least-once configuration, what happens on rebalance?
- A. The 300 processed records are skipped and processing resumes at record 301, giving exactly-once
- B. All 500 records are redelivered to another consumer, so the first 300 are processed twice ✓
- C. The uncommitted 300 records are lost permanently because their offsets were fetched
- D. Kafka replays only the 200 unprocessed records because it tracks per-record acks like a traditional queue
Correct answer: B. Kafka commits offsets per partition, not per record, so with no commit for the batch the new owner re-reads from the last committed offset and reprocesses all 500 — hence at-least-once delivery requires idempotent processing to tolerate the 300 duplicates.
Two transactions deadlock repeatedly in production: T1 updates row A then row B; T2 updates row B then row A. The database detects the cycle and aborts one victim, but throughput still suffers from frequent retries. Which fix eliminates the deadlock cycle itself rather than just handling its symptom?
- A. Raise the deadlock detection timeout so the database waits longer before choosing a victim
- B. Enforce a consistent global lock-acquisition order (always lock A before B) in all code paths ✓
- C. Lower the isolation level to READ UNCOMMITTED so the updates no longer take row locks
- D. Wrap each transaction in an application-level retry loop with exponential backoff
Correct answer: B. A deadlock requires a circular wait; acquiring resources in a consistent global order makes a cycle impossible, whereas retries and longer timeouts only cope with deadlocks after they form and READ UNCOMMITTED still takes write locks.
A write-heavy 'user activity feed' table is sharded by `shard = hash(user_id) % N`. A handful of celebrity users generate 40% of all writes, saturating a few shards. You must rebalance without downtime and stop the hot partitions. What is the soundest change?
- A. Switch the shard key to `hash(timestamp)` so writes spread evenly across shards over time
- B. Increase N and rehash everything at once during a maintenance window to rebalance load
- C. Use a composite/compound shard key such as hash(user_id, bucket) that splits a hot user's writes across several sub-partitions ✓
- D. Add read replicas to the hot shards so the write load is distributed across the replicas
Correct answer: C. Salting the key with a per-user bucket spreads a single hot user's writes across multiple partitions, curing the hotspot; timestamp keys create a moving write hotspot, and replicas do not absorb write load.
In a Saga using choreography (services react to each other's events with no central coordinator), the flow is Order → Payment → Inventory → Shipping. Inventory fails and emits a compensation event. Six months later you must add a Fraud-check step between Payment and Inventory. Which drawback of choreography does this expose most sharply?
- A. Choreography cannot implement compensating transactions, so partial rollback is impossible
- B. The distributed control flow is implicit across many services, making it hard to reason about, add steps to, and debug the end-to-end sequence ✓
- C. Choreography forces synchronous calls, so adding a step increases end-to-end latency linearly
- D. Events in choreography cannot carry a correlation ID, so tracing the saga is impossible
Correct answer: B. Choreography scatters the workflow logic across event handlers with no single place that describes the sequence, so understanding and modifying the flow is hard — the readability/maintainability tradeoff orchestration addresses by centralizing control.
An HTTP/1.1 backend service opens a new TCP connection per outbound call to a downstream dependency under high load and you observe rising latency and TIME_WAIT socket exhaustion. Migrating the client to HTTP/2 with a connection pool helps most because of which specific mechanism?
- A. HTTP/2 compresses response bodies, reducing bytes transferred per call
- B. HTTP/2 multiplexes many concurrent requests over a single long-lived TCP connection, avoiding per-request connect and TIME_WAIT churn ✓
- C. HTTP/2 uses UDP instead of TCP, eliminating the TCP handshake entirely
- D. HTTP/2 removes the need for TLS, cutting the handshake round-trips
Correct answer: B. HTTP/2 stream multiplexing lets many concurrent requests share one persistent connection, removing per-request TCP/TLS handshakes and the TIME_WAIT accumulation from connection churn; it does not use UDP (that's HTTP/3) nor drop TLS.
A service protects a slow downstream with a circuit breaker plus retries: 3 retries with exponential backoff on every failed call. During a downstream brownout, the breaker is configured to open at 50% error rate, but the outage still cascades and amplifies. What is the most likely root cause of the amplification?
- A. The retries multiply load onto the already-struggling downstream (a retry storm) faster than the breaker trips, so aggregate traffic spikes 4x ✓
- B. The exponential backoff jitter makes retries too slow, so the breaker never sees enough failures to open
- C. Circuit breakers are incompatible with retries and must never be combined
- D. The 50% threshold is too low, so the breaker opens prematurely and blocks healthy traffic
Correct answer: A. Unbounded retries stacked on a failing dependency multiply request volume (a retry storm) and amplify the overload, which is why retries need a shared retry budget, jitter, and to be suppressed while the breaker is open.
You need optimistic concurrency for a `wallets` table to prevent lost updates on balance edits. Which SQL pattern correctly detects a concurrent modification and lets the application retry, rather than silently overwriting?
- A. UPDATE wallets SET balance = balance - 10 WHERE id = 1
- B. UPDATE wallets SET balance = :new, version = version + 1 WHERE id = 1 AND version = :read_version, then check affected-rows = 1 ✓
- C. SELECT balance FROM wallets WHERE id = 1 FOR UPDATE, then UPDATE with the new balance
- D. UPDATE wallets SET balance = :new WHERE id = 1 AND balance = balance
Correct answer: B. The version-guarded UPDATE affects zero rows if another writer bumped the version since your read, signaling a conflict to retry — that compare-and-set is the essence of optimistic locking, while option 2 is pessimistic and option 0/3 can silently lose the concurrent update.
Under PostgreSQL's default READ COMMITTED isolation, a transaction runs the same range query twice and gets different row counts. Which phenomenon is NOT prevented at this level?
- A. Dirty read
- B. Phantom read ✓
- C. Cascading rollback
- D. Torn write
Correct answer: B. READ COMMITTED prevents dirty reads but still permits phantom and non-repeatable reads, since each statement sees a fresh snapshot.
In the CAP theorem, a network partition occurs between two replicas that both accept writes. To keep the system Available, which property must be sacrificed?
- A. Partition tolerance
- B. Consistency ✓
- C. Durability
- D. Isolation
Correct answer: B. During a partition, a system must choose between Consistency and Availability; staying available means tolerating temporary inconsistency.
You use optimistic concurrency with a version column. A client sends UPDATE ... SET v=v+1 WHERE id=? AND v=?. The update affects 0 rows. What does this indicate?
- A. The row was deleted by a foreign key cascade
- B. A concurrent transaction modified the row first ✓
- C. The database index is corrupt
- D. The isolation level is too high
Correct answer: B. Zero affected rows means the version no longer matches, signaling a concurrent modification that the client must retry against fresh data.
A service experiences cascading failures when a downstream dependency slows down and threads block waiting on it. Which pattern most directly prevents this?
- A. Retry with exponential backoff
- B. Circuit breaker ✓
- C. Database sharding
- D. Content negotiation
Correct answer: B. A circuit breaker trips after repeated failures/timeouts, failing fast and freeing threads instead of letting them pile up on a slow dependency.
In Kafka, a consumer group's partition is reassigned mid-batch and offsets were committed before processing completed. What is the resulting risk?
- A. Messages are duplicated
- B. Messages are lost (not reprocessed) ✓
- C. The partition becomes read-only
- D. The broker rejects the commit
Correct answer: B. Committing offsets before processing means a rebalance can skip unprocessed messages, causing data loss; commit after processing for at-least-once.
Two transactions each hold a lock the other needs, and the database aborts one. What guarantees this abort will eventually happen automatically?
- A. Two-phase commit
- B. Deadlock detection via a wait-for graph ✓
- C. Write-ahead logging
- D. Multiversion concurrency control
Correct answer: B. The engine builds a wait-for graph and, on detecting a cycle, chooses a victim transaction to abort, breaking the deadlock.
A REST endpoint must remain safe to retry after a client timeout without creating duplicate charges. Which mechanism is the industry-standard solution?
- A. A server-side rate limiter
- B. An idempotency key stored and checked per request ✓
- C. A longer HTTP timeout
- D. Switching from POST to PUT
Correct answer: B. An idempotency key lets the server detect a retried request and return the original result instead of re-executing the side effect.
In a database using MVCC, long-running read transactions can cause storage bloat. Why?
- A. They hold exclusive write locks on every row
- B. They prevent vacuuming of old row versions still visible to them ✓
- C. They rewrite the entire table on commit
- D. They duplicate indexes for isolation
Correct answer: B. Old tuple versions cannot be reclaimed while an open transaction might still need to see them, so long readers block vacuum/GC and bloat storage.
You need strictly ordered, exactly-once side effects across a distributed transaction spanning two microservices. Which pattern trades a distributed lock for eventual consistency with compensations?
- A. Two-phase commit (2PC)
- B. Saga pattern ✓
- C. Leader election
- D. Bloom filter
Correct answer: B. The Saga pattern sequences local transactions with compensating actions on failure, avoiding a blocking distributed lock at the cost of eventual consistency.
A hash-based sharding scheme rehashes all keys whenever a node is added, causing massive data movement. Which technique minimizes this reshuffling?
- A. Range partitioning
- B. Consistent hashing ✓
- C. Round-robin assignment
- D. Composite indexing
Correct answer: B. Consistent hashing maps nodes and keys onto a ring so adding/removing a node only remaps keys near that node, minimizing data movement.
Two concurrent transactions read a counter = 5, each add 1, and write 6, losing an update. Which approach prevents this lost update without full table locking?
- A. Setting isolation to READ UNCOMMITTED
- B. Optimistic concurrency using a version column with a conditional UPDATE ✓
- C. Adding an index on the counter column
- D. Using a larger connection pool
Correct answer: B. Optimistic concurrency (compare-and-set on a version/value) makes the write fail if the row changed since it was read, preventing lost updates.
In a distributed system, the CAP theorem states that during a network partition you must choose between:
- A. Latency and throughput
- B. Consistency and availability ✓
- C. Durability and atomicity
- D. Sharding and replication
Correct answer: B. CAP says that when a partition (P) occurs, a system must sacrifice either consistency or availability; it cannot guarantee both.
Why can adding an index on a low-cardinality boolean column often fail to help (and the planner ignore it)?
- A. Boolean columns cannot be indexed
- B. The optimizer estimates a large fraction of rows match, making a sequential scan cheaper than random index lookups ✓
- C. Indexes require unique values
- D. B-trees do not support equality lookups
Correct answer: B. When an index would return a large fraction of the table, random I/O per row makes a sequential scan cheaper, so the planner skips the index.
In an eventually consistent system using async replication, a user updates their profile then immediately reads it and sees stale data. What consistency guarantee would fix this specific case?
- A. Strong consistency across all nodes
- B. Read-your-writes (session) consistency ✓
- C. Causal consistency for unrelated writes
- D. Monotonic reads only
Correct answer: B. Read-your-writes consistency guarantees a client always sees its own prior writes, resolving the stale self-read after an update.
A service under load exhausts its database connection pool and requests hang. Which combination best mitigates cascading failure?
- A. Unbounded connection creation plus infinite timeouts
- B. Bounded pool with fast-fail timeouts and a circuit breaker ✓
- C. Disabling connection pooling entirely
- D. Switching all queries to SELECT *
Correct answer: B. A bounded pool with timeouts prevents unbounded resource use, and a circuit breaker sheds load fast so failures don't cascade.
In two-phase commit (2PC), what is the fundamental availability weakness?
- A. It cannot handle more than two participants
- B. If the coordinator fails after prepare, participants may block indefinitely holding locks ✓
- C. It requires all nodes to share one clock
- D. It only works on a single database
Correct answer: B. 2PC is a blocking protocol: a coordinator crash after the prepare phase can leave participants holding locks with no way to safely decide.
You need exactly-once processing semantics from an at-least-once delivery queue. What is the standard practical approach?
- A. Enable higher QoS on the broker
- B. Make consumers idempotent and deduplicate on a message/business key ✓
- C. Increase the visibility timeout to infinity
- D. Use larger batch sizes
Correct answer: B. True exactly-once delivery is generally infeasible; the practical pattern is at-least-once delivery plus idempotent consumers that dedupe by key.
A hot partition in a sharded database, caused by a monotonically increasing shard key, is best resolved by:
- A. Adding read replicas to that shard
- B. Choosing a shard key with high, evenly distributed cardinality (e.g., hashing the key) ✓
- C. Increasing the shard's page cache
- D. Lowering the isolation level
Correct answer: B. Hashing or otherwise randomizing the shard key spreads writes evenly across shards, eliminating the hotspot from sequential keys.
In a high-throughput write path, why might an append-only log-structured merge (LSM) tree outperform a B-tree storage engine?
- A. LSM trees never need compaction
- B. LSM converts random writes into sequential writes and buffers in memory, improving write throughput ✓
- C. B-trees cannot store more than 4KB pages
- D. LSM eliminates the need for a write-ahead log
Correct answer: B. LSM trees batch writes in memory and flush sequentially, turning costly random I/O into sequential I/O, which boosts write-heavy workloads.
When implementing cursor-based (keyset) pagination instead of OFFSET/LIMIT on a large table, the main benefit is:
- A. It supports arbitrary jump-to-page navigation
- B. Constant-time page fetches because it seeks by an indexed key rather than scanning and discarding offset rows ✓
- C. It removes the need for an ORDER BY
- D. It guarantees no duplicate rows regardless of concurrent inserts
Correct answer: B. Keyset pagination seeks directly via an indexed column, avoiding the growing scan-and-discard cost that makes large OFFSET values slow.