Event Registration
A fair registration system for ~700 people chasing 500 seats — first to arrive, not fastest to type.
What it is
The sign-up site for a youth retreat: a countdown, a 4-step form with autosave, then a payment code and PayPal checkout. It is built for the moment registration opens and about twice as many people as there are seats arrive at once.
Why I built it
Fairness was the whole brief: your place should depend on when you arrived, not how fast you can type, and everyone who gets a ticket should be able to finish their form. We expected around 700 people for 500 seats — on several devices, refreshing constantly — so it also had to never sell more seats than exist.
How it works
Opening the form creates a ticket whose number is the database's auto-increment id. Your position is the count of earlier tickets that are still live, plus one — so when someone times out or is merged, everyone behind moves up.
A cookie brings back the same ticket after a refresh, and answers autosave 2 seconds after you stop typing. Each ticket gets 15 minutes to finish the form.
On submit, the same name plus a matching phone, email or date of birth counts as a duplicate. The person can merge, which keeps the lower (earlier) ticket.
In production everyone received a payment code (church tag + 8 characters) and redeemed it at the same moment. Each redemption runs in one transaction that locks the max_seats settings row with SELECT … FOR UPDATE as a global mutex, counts paying + registered, then either reserves a seat or moves the person to a waitlist ordered by when they tried.
With 700 simultaneous redemptions for 500 seats the result was exactly 500 seats and 200 on the waitlist — never more. An earlier 700-user test report had flagged race conditions under load and recommended SELECT … FOR UPDATE inside a transaction, which is the approach the redemption uses.