Tickets, clinic appointments, limited drops. Released to a crowd, never oversold, and verifiable by anyone.
Live demo · Technical deep-dive · Architecture · Submission notes
Every high-demand release hits the same bug: a clinic double-books an appointment, a venue sells more tickets than it has, a drop crashes and no one can prove the winners were fair. Counting one scarce resource under a crowd is genuinely hard.
Singleton makes it the easy path. A provider releases a fixed batch of slots and gets three guarantees:
- Correct: the batch can never oversell, no matter how many people claim at the same instant.
- Fair: strict first-come order, or equal odds inside an entry window. One slot per person, no line-jumping.
- Verifiable: every claimant gets a receipt whose rank is re-checkable against a public ledger, and a lottery's entire winner list can be recomputed in the visitor's own browser.
Why Amazon Aurora DSQL? Guaranteeing "never oversell" under a flash crowd needs strong consistency and serverless scale at the same time. Aurora DSQL gives both, so the whole guarantee collapses into one ordinary ACID transaction (a sharded conditional decrement with optimistic-concurrency retry) instead of a Redis lock, a queue, or a reconciliation job.
It is also a multi-tenant marketplace: operators self-register and manage only their own releases (server-enforced), browsable through a category filter rail. The front end was scaffolded with v0 and deployed on Vercel in the same region as the cluster.
A release's capacity is split across shard_count counter rows (release_shards). A claim:
- short-circuits if the claimant already holds a slot (idempotent, no write);
- picks a random shard order and, per shard, runs one transaction:
UPDATE release_shards SET remaining = remaining - 1 WHERE … AND remaining > 0 RETURNING id, thenINSERTthe allocation, thenCOMMIT; - retries the whole claim on a commit-time OCC conflict (
SQLSTATE 40001/OC000) with exponential backoff + jitter; - joins a fair waitlist when every shard is empty (sold out).
A single hot counter melts under Aurora DSQL's optimistic concurrency control, so sharding the counter is the one load-bearing decision. The CHECK (remaining >= 0) constraint plus the conditional decrement make oversell impossible; the unique index on (release_id, claimant_id) makes a retried claim idempotent. Ranks are derived from (claimed_at, id) order, never stored, so they are exactly 1..allocated.
See src/domain/claim.ts (the heart), src/db/retry.ts, and scripts/stress.ts.
First-come rewards latency: a datacenter bot beats a human on hospital wifi every time. Mode B removes speed from the game. Everyone who enters during the window is an equal entrant. When the window closes, one atomic transaction:
- generates a 32-byte seed at creation and publishes only its SHA-256 commitment;
- accumulates entries (idempotent, one per claimant);
- scores every entry as
sha256(seed + ":" + entryId), sorts ascending, takescapacity, consumes the shards, and reveals the seed, all in one ACID transaction, idempotent via adrawn_atguard; - lets the verify page re-run the entire draw in the browser (WebCrypto) and show MATCH.
A release is lottery mode iff a lottery_config row exists (no change to Mode A behavior). Draw proofs expose entry UUIDs only, never claimant identities. See src/domain/lottery.ts, src/domain/draw.ts, and src/components/lottery-proof.tsx.
resolveActor maps every request to a platform super-admin (master ADMIN_TOKEN) or an operator (a per-provider api_key); authorizeReleaseMutation enforces that an operator can delete or draw only on releases it owns. All of it is additive across seven migrations. See src/lib/admin.ts and docs/INTEL.md §15.
DSQL speaks the PostgreSQL wire protocol but is not full PostgreSQL. Verified against the current AWS Aurora DSQL User Guide.
| Constraint | How Singleton handles it |
|---|---|
| No foreign keys | Relationships enforced in app code; unique indexes where they help. |
| No sequences / SERIAL | App-generated UUID PKs via crypto.randomUUID(). |
| CHECK constraints ARE supported | Kept as real DB-enforced invariants (capacity > 0, remaining >= 0). |
| DDL is async | Indexes use CREATE INDEX ASYNC; the migrate runner polls pg_index.indisvalid. |
| 1 DDL per txn, no DDL+DML mixing | Each migration statement runs in its own transaction. |
| 3,000-row / 10 MiB / 5-min txn caps | Claims write 1 row; the cascade delete batches under the cap. |
| OCC, REPEATABLE READ only | App retries SQLSTATE 40001 (OC000/OC001) with backoff. |
| 60-min connection cap, 15-min token TTL | The official connector mints a fresh IAM token per connection and recycles connections. |
| IAM auth only | No static DB password; @aws/aurora-dsql-node-postgres-connector + the AWS credential chain. |
TypeScript (strict) · Node 20+ · Next.js 15 (App Router, Node runtime) · Tailwind v4 + shadcn/ui + lucide-react · Amazon Aurora DSQL · pg + @aws/aurora-dsql-node-postgres-connector · raw parameterized SQL (no ORM) · Zod · Vitest · Playwright · v0 (front-end scaffolding) · Vercel.
# 1) Provision Aurora DSQL (Windows: use the .ps1 variants)
./scripts/provision/single-region.sh us-east-1 # creates the cluster, prints the endpoint
# 2) Configure + initialize
cp .env.example .env.local # fill in the printed endpoint + AWS_REGION + ADMIN_TOKEN
npm install
npm run migrate # applies db/migrations (async indexes; waits for valid)
npm run seed # demo provider + open release, prints its URL
npm run dev # http://localhost:3000
# 3) Prove the guarantee (the core gate)
npm run stress -- --attempts 10000 --capacity 200 --shardCount 32 --concurrency 64The stress harness asserts, with a non-zero exit on any violation: allocations === min(attempts, capacity), oversells === 0, every claimant distinct with one slot, and derived ranks exactly 1..allocated. The same proof is available in the UI under Admin → a release → Run burst.
npm run test # Vitest unit + integration (integration auto-skips without DSQL)
npm run test:e2e # claim → receipt → verify, sold-out, cross-tab consistency, lottery MATCHImport the repo (framework: Next.js). vercel.json pins functions to iad1 (≈ us-east-1) to colocate with the cluster. Add encrypted env vars (AWS_REGION, DSQL_CLUSTER_ENDPOINT, ADMIN_TOKEN, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY), deploy, and hit /api/health. The DB stack runs on the Node runtime (never Edge) with a module-scope pool drained via attachDatabasePool for Fluid Compute.
Full environment-variable reference and multi-region setup: docs/INTEL.md.
app/ # routes (App Router) + app/api/** route handlers
src/
db/ # pool, query (+ failover), releases, allocations, lottery, providers, retry
domain/ # claim (the heart), draw (the lottery), rank, shards, lottery hashing
components/ # shadcn/ui surfaces (intake, lottery, admin, releases-browser, v0/)
lib/ # admin auth + actor resolution, categories, image + sha256 helpers
db/migrations/ # 0001 init · 0002 indexes · 0003 lottery · 0004 lottery indexes
# · 0005 release_meta · 0006 provider_keys · 0007 release_category
scripts/ # migrate · seed · stress (fcfs + lottery) · provision/*
tests/ # unit · integration (real DSQL) · e2e (Playwright)
docs/ # INTEL.md (deep dive) · architecture · SUBMISSION · screenshots · v0
- Connects to Aurora DSQL via the official node-postgres connector with IAM auth only (no password).
- Migrations apply cleanly with ASYNC indexes; no FK / sequence / trigger / extension usage.
- Claim is idempotent, shards the counter, retries on
40001/OC000with capped backoff. - Stress (10,000 vs 200 / 32 shards): oversells 0, exactly 200 allocated, ranks 1..200, green against a live cluster.
- Mode B lottery: 5,000 entries → 200 distinct winners → byte-for-byte browser re-derivation (MATCH) → repeat draw is a no-op.
- Multi-tenant ownership (platform vs operator), server-enforced; three adversarial review passes, all findings fixed.
- Unit + integration + Playwright suites green against the live cluster.
- Deployed on Vercel: singleton-six.vercel.app.




