The problem
Auctions combine hard consistency rules (reserve prices, minimum increments, start and end times) with bursty, real-time traffic. Every bidder needs to see a new high bid within moments, two simultaneous bids must never both win, and the business needs a complete, queryable history of what happened.
Key design decisions
- 01
Enforce bidding rules with conditional writes
The auction item stores the next minimum acceptable bid. A transactional write records the bid and updates the auction only if the new amount meets that minimum and the auction is still open, so simultaneous bids are resolved by the database, not by locks in application code.
- 02
Single-table design for auction access patterns
Auctions, bids and bidder views share one table with composite keys, so the hot paths (current state, bid history, a bidder's activity) are each a single query.
- 03
Publish events from the database, not the function
Accepted bids flow from DynamoDB Streams through EventBridge Pipes onto the event bus. An event is emitted only if the write committed, and a crash between saving and publishing can never lose one.
- 04
Durable work behind queues
Consumers that do work, such as outbid notifications, read from their own SQS queue with retries, a dead-letter queue and redrive, so a failing downstream never loses an event or blocks the others.
- 05
Push updates over MQTT
A small publisher function forwards each new bid to per-auction IoT Core topics, which browsers receive over MQTT on secure WebSockets, with no connection servers to manage.
- 06
Event history in a queryable data lake
EventBridge also delivers every event to Firehose, which writes compressed batches to S3 for auditing and Athena analytics at storage prices.