Inspiration

I've played enough online games to have watched an economy die. Someone finds a dupe glitch, suddenly there are at least thousand of an item that's supposed to be rare, prices go bonkers, and the studio ends up rolling back servers or banning waves of accounts. The game, 'New World' had to switch off trading during its dupe crises; 'RuneScape' and 'Diablo' have their own set of dupe errors. What stuck with me is that this is almost never a gameplay bug. It's a database bug. A trade is "give the item to B, take it from A," and if those two writes aren't one serializable transaction, the wrong kind of concurrency leaves the item in two places at once. I wanted to see if I could make that specific failure flat-out impossible, and prove it instead of just claiming it.

What it does

One of One is a trading layer for game items where every item exists in exactly one player's inventory and stays that way, even when a crowd tries to grab the same item at the same instant.

There are two screens. The economy view shows players and their inventories with a live integrity badge: minted vs held, and whether the economy is CONSERVED or BROKEN. The exploit console is the fun part. You pick an item, choose how many simultaneous trades to fire at it, and pick the transfer mode. In naive mode it duplicates the item in front of you. In safe mode the exact same attack does nothing but get rejected. Every number on screen is read straight from the database, not faked in the UI. The invariant I'm defending is simple: $held = minted$, and no item_id ever appears in more than one holdings row.

How I built it

Next.js (App Router) on Vercel, with Amazon Aurora DSQL as the database, wired up through the Vercel marketplace integration so auth is IAM/OIDC with no passwords anywhere. The schema is DSQL-safe: no foreign keys, no sequences, UUIDs generated in app code. The one table that matters is holdings, which holds exactly one row per item.

The whole project lives in lib/transfer.ts. The safe path is one serializable transaction doing a conditional single-row move: UPDATE holdings SET owner_id = B WHERE item_id = X AND owner_id = A, retrying on serialization conflicts. Because it's an UPDATE of one existing row, there's physically no second row to create, and because concurrent grabs all hit the same row, DSQL's optimistic concurrency lets exactly one win and bounces the rest with SQLSTATE 40001. The naive path is the honest anti-pattern: check ownership, then INSERT a new holding and DELETE the old one as separate, non-atomic statements.

To finish it I wrote a CLI gate (npm run exploit -- --gate) that seeds one item, fires 100 concurrent trades in each mode, and fails loudly if the safe mode ever duplicates.

Challenges I ran into

The funniest one: I deleted my own DSQL cluster partway through and spent a confused few minutes watching DNS fail before realizing the endpoint was just gone. Reprovisioning through Vercel taught me something useful, because the new integration injected its env vars with a PGUSER_ prefix instead of the bare PGHOST/AWS_ROLE_ARN names my connection code expected, so nothing connected until I made the pool read both. The subtler challenge was making the naive bug real. It only duplicates because each concurrent INSERT targets a different primary key, so DSQL sees no conflict and commits them all. That detail is the entire point, and it took some thinking to make sure I am demonstrating an honest failure mode and not a rigged one.

Accomplishments that I'm proud of

The gate passing on a real cluster. 100 simultaneous grabs of one item: 'naive' ended with the item in dozens of inventories and the economy BROKEN; 'safe' committed exactly one trade, rejected the other 99, absorbed multiple serialization conflicts with retries, and stayed CONSERVED. Watching one sword item show up in three players' bags at once, then watching the safe mode shrug off the identical attack, is honestly satisfying. I'm also happy the demo is fully honest. Every figure comes from a real audit query against committed state.

What I learned

How optimistic concurrency actually behaves under contention, and why high-cardinality keys are exactly what a database like DSQL wants. A player economy is millions of independent items and player IDs, so writes spread out naturally and the only place anything ever contends is the one item two people are fighting over, which is precisely where we want the contention to be. I also came away convinced that for this problem the database choice isn't a detail, it's the feature. Serializable, strongly consistent writes with no single lock bottleneck are what make the guarantee hold.

What's next for One of One

Right now it runs in a single region. The obvious next step is multi-region, since DSQL is active-active and the same guarantee should hold globally with no single lock manager. Beyond that: proper auction or queue semantics for genuinely scarce items (where everyone contending on one row is expected), signed trade receipts for an auditable history, and a small SDK so a real game backend could drop this in as its custody layer instead of rolling its own and hoping to not get this issue.

Built With

Share this project:

Updates