Inspiration

Group-buying is a proven, massive consumer model, but it's always been asynchronous — you commit, you wait, you find out later. I wanted the opposite: a live market where a global crowd watches one price fall together in real time, and everyone wins the same deal. The moment I sketched it, the hard part was obvious: if two shoppers in two regions ever see a different price for the same item at the same instant, the whole thing is unfair and exploitable. That's not a UI problem — it's a database problem. So the product became an excuse to lean on the one capability that makes it honest: a globally, strongly-consistent database.

What it does

Shoppers join a live "rally" for a product. As more people pile in worldwide, the unit price melts down through volume tiers — and when the timer ends, everyone settles at the same final price, fair to the cent. Early joiners get the deal the crowd earned. Sellers launch a rally in under a minute; the marketplace shows live drops melting in real time. The whole promise is verifiable, not marketing: a public /proof page reconciles a real settled rally live and shows distinct prices paid = 1 and ledger drift = \$0.00, with the exact SQL you can run yourself, plus the same item's live count read from two AWS regions at once.

How we built it

The core is a small, pure SQL + JavaScript fairness engine on Aurora DSQL. The live price is never stored — it's a derived read, tier(sum(count_shards)) — so crossing a tier lowers the price for everyone atomically, with no tier-transition race to lose. The join counter is sharded across 128 rows so the hottest write doesn't become an optimistic-concurrency hot row; a random shard is bumped per join and the live count is their consistent sum. Joins are idempotent on a unique (rally_id, user_id), so a double-tap never double-counts. Settlement reads the final count once, charges everyone that single price, and writes a balanced double-entry ledger, idempotent per user. DynamoDB is the live read plane: each committed join projects a {count, price, tier} frame to a live_frame item, and the Next.js room streams it over SSE, so the broadcast never touches the DSQL write path. The app is Next.js on Vercel, with functions pinned to Tokyo next to the DSQL primary.

Challenges we ran into

Porting the engine to DSQL surfaced the real differences fast. DSQL rejects BEGIN ISOLATION LEVEL SERIALIZABLE (0A000) — but it's serializable-by-default with optimistic concurrency, so a plain BEGIN gives identical retry semantics. It has no sequences and constraints on secondary indexes, so unique email/handle are enforced with PK-guard tables and INSERT ... ON CONFLICT instead of unique indexes, and indexes are created ASYNC. The realtime path was the sneakiest bug: an in-process event emitter fanned joins to SSE clients perfectly in dev, then silently broke on Vercel because each serverless invocation is isolated — so I made the shared DynamoDB live_frame the cross-instance source of truth, and the deployed app became correct across instances. Settling 2,000 users across the Pacific took ~456s with sequential per-row inserts; rewriting it to set-based batched inserts cut it to 3.6s, same guarantees.

Accomplishments that we're proud of

The fairness proof holds on the real cluster, not in theory. A run on Tokyo Aurora DSQL: 2,500 join attempts (including 500 duplicate taps) gave exactly 2,000 unique joiners, the shard sum matching to the unit, 398 optimistic-concurrency conflicts detected and retried to success, zero double-joins, the price melting \$100 to \$52, and at settlement distinct prices paid = 1, ledger drift = 0, zero double-charges. Tokyo and Seoul agree on the live count and price tick-for-tick (cross-region read 130–220 ms), and killing one region mid-rally keeps joins flowing with no lost counts. And it's a real product around that core — a marketplace, seller tools, accounts, simulated-but-modeled payments, receipts, and notifications — not a single demo screen.

What we learned

The cleanest way to win a "why this database" argument is to make the database do something the obvious tool can't, then make it checkable. "One falling price across regions, settled fairly" is only honest under strong consistency — under eventual consistency it's exploitable — so the product and the database choice justify each other. I also learned to respect the boundary between the OLTP write truth and the read plane: every time I was tempted to read the live price with a DSQL aggregate scan for fan-out, the right answer was the DynamoDB frame. And serverless makes you externalize state you didn't think was state — the in-process emitter was that lesson.

What's next

Real payments (the ledger and settlement are already real; only the charge is simulated). Recurring drops and follower analytics for power sellers. Pushing the DynamoDB Streams to Lambda to WebSocket scale path (enabled and documented) to true million-watcher fan-out. And a Pro-tier cron so scheduled drops auto-launch to the second instead of on first browse.

Built With

Share this project:

Updates