Reason About Indexes, Kafka, and Database Locking
PersistenceSoftware Engineer · OnsiteLast updated
Tests practical database indexing, Kafka event ingestion with idempotency guarantees, and row-level locking strategies to prevent concurrency bugs and deadlocks in an inventory and order processing pipeline.
Scenario
You are designing the backend persistence and event processing layer for an e-commerce platform handling flash sales. The system consumes order placement events from Apache Kafka and updates both customer order records and item inventory counts in a relational database (PostgreSQL-compatible).
Database Schema
CREATE TABLE orders (
order_id UUID PRIMARY KEY,
user_id UUID NOT NULL,
status VARCHAR(32) NOT NULL, -- 'PENDING', 'CONFIRMED', 'CANCELLED'
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
total_amount NUMERIC(10, 2) NOT NULL
);
CREATE TABLE order_items (
order_id UUID REFERENCES orders(order_id),
item_id UUID NOT NULL,
quantity INT NOT NULL,
PRIMARY KEY (order_id, item_id)
);
CREATE TABLE inventory (
item_id UUID PRIMARY KEY,
available_stock INT NOT NULL CHECK (available_stock >= 0),
reserved_stock INT NOT NULL DEFAULT 0
);
Workload & System Requirements
-
Query Workload:
- High-frequency query: Fetch the 20 most recent confirmed orders for a given user:
SELECT * FROM orders WHERE user_id = ? AND status = 'CONFIRMED' ORDER BY created_at DESC LIMIT 20; - Periodic analytics: Find orders created within a timestamp range across all users.
- High-frequency query: Fetch the 20 most recent confirmed orders for a given user:
-
Event Consumption:
- An upstream service publishes
OrderCreatedEvent(order_id, user_id, items: [(item_id, quantity)])to a partitioned Kafka topicorders.created. - Multiple consumer instances run in a single consumer group.
- Delivery is at-least-once: network retries or consumer rebalances can deliver the same message more than once.
- An upstream service publishes
-
Stock Reservation & Concurrency:
- For each valid event, the consumer must verify sufficient stock and reserve it (
available_stock -= qty,reserved_stock += qty) atomically with marking the order confirmed. - Multiple concurrent orders can request the same items or overlapping item sets simultaneously.
- For each valid event, the consumer must verify sufficient stock and reserve it (
Questions to Address
-
Index Design:
- Propose the exact composite index definition for
ordersto serve the user order query without table scans or separate sorting steps. Explain column ordering. - Evaluate whether a partial index would be beneficial here.
- Propose the exact composite index definition for
-
Kafka Partitioning & Idempotency:
- What partition key should the producer use on
orders.created? Explain how partition assignment affects concurrent processing across items vs. users. - How should the consumer handle duplicate deliveries to guarantee that inventory is decremented exactly once per order?
- What partition key should the producer use on
-
Concurrency Control & Deadlock Prevention:
- Write out the transactional SQL logic (or pseudo-code) for reserving stock across multiple items in an order.
- Explain how concurrent transactions updating overlapping sets of items (e.g., Order A reserves items [1, 2] while Order B reserves items [2, 1]) can deadlock, and describe your strategy to guarantee deadlock-free execution with bounded retries.
Hints
Hint 1
For multi-column indexes covering equality, inequality/range, and sorting operations, order columns by equality predicate first, followed by the sorting column.
Hint 2
To achieve idempotent processing at-least-once, use a transactional outbox or an idempotency record committed inside the exact same database transaction that decrements stock.
Hint 3
Deadlocks caused by concurrent lock acquisition on overlapping sets of rows can be eliminated by enforcing a strict global acquisition order on row keys before locking.
Follow-up questions
- How does your index strategy change if users can query orders across any arbitrary status filter rather than only 'CONFIRMED'?
- If a single hot SKU receives 10,000 reservation attempts per second, how would you mitigate database row-lock contention on that single row?
- Under what conditions would using optimistic concurrency control (e.g., version columns) be preferred over pessimistic row locks (`SELECT ... FOR UPDATE`) in this scenario?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.