Book Events — the tightest constraint holds the gate.
Every event ticketing app counts seats. Almost no real venue is limited by seats. A farm dinner is limited by seats and kitchen staff; a pottery studio by wheels and kilns; a goat yoga class, genuinely, by goats. Sell a family of five into a room that has the chairs but not the second cook, and the merchant finds out on the night.
Book Events models capacity as resource pools. A booking draws weighted amounts from several at once and the tightest one binds — and when it binds, the shopper is told which constraint stopped them, in the merchant’s own words, rather than watching a button fail.
It is an embedded Shopify app, which means the interesting problems are boundary problems. Money only moves through the merchant’s own checkout, so events have to become products and ticket types variants and stay in sync. The theme’s own Buy-it-now button is a second front door that skips the date, the attendee details and the capacity hold — so it isn’t hidden, it’s refused by a checkout validation function, because a control you can only see in the UI is not a control.
This is the product where the operating model shows up most plainly as documents. Eleven architecture decision records, each naming the Jira issues it constrains and the vendor documentation it was checked against, with the date. Written for a reader who will be an AI as often as a person — and a decision whose blast radius isn’t on the record gets relitigated every single time.
Visit bookevents.app
- Resource pools, not seat counts The whole product. A booking draws weighted amounts from several pools at once — seats, staff, mats, kits, goats — and the tightest one binds. When a family of five can’t book, the shopper is told which constraint stopped them, in the merchant’s own words, instead of watching the button fail.
- A schema built for the migration it hasn’t done yet A pool’s identity is shop-level from day one and only its capacity is per-occurrence, so sharing one pool across overlapping occurrences later is an additive migration rather than a merge of N rows and a rewrite of every consumption record.
- Money only ever moves through Shopify Checkout One product per event, one variant per ticket type, synced on create, update and archive — and the capacity hold is taken before the cart, not after.
- The storefront works out of the box A theme app embed plus a Cart and Checkout Validation Function, because the theme’s own Buy-it-now button is a second way to buy that skips the date, the attendee details and the hold. Hiding it in the UI isn’t enough; the function refuses the checkout.
- Disruption handling as a first-class path A farm looks at a storm forecast at 6am and cancels tomorrow’s tour from a phone, with forty valid-looking tickets outstanding: cancel, bulk reschedule, refund, notify, and an audit trail of who did what.
- Signed tickets, and a ledger of what was delivered Ticket codes are signed and revocable, and every send is recorded — so a refunded ticket stops working at the gate and someone can prove the email went out.
- Every model call goes through one gateway No provider SDK is imported and no provider key is stored: one gateway key, one budget, one dashboard, and the model behind a feature is a configuration change rather than a dependency.
- Eleven architecture decisions on the record Each ADR names the Jira issues it constrains and the vendor documentation it was verified against, with the date. A decision whose blast radius isn’t written down gets relitigated every time someone new reads the code — and here that someone is usually the model.
- 447 tests Across 61 files, including tenant-isolation and capacity-concurrency suites that run against a real Postgres rather than a mock.
Register · Book Events
Built over one month: 70 features, 15 pull requests, every one reviewed.
github.com/productdetroit- Work items delivered
- 70Stories and tasks closed Done in Jira, in production.
- Median idea → live
- 6hoursMedian created → resolved, all issue types.
- Specs written
- 8Problem, data model, architecture decision — before code.
- Pull requests merged
- 15
- Production deploys
- 73
- Lines of code
- 14,657
- Reviewed by me
- 100%