A business school event, with more riding on the registration page than it appears. 300 seats split into 6 sessions of 50 each; registrants fall into three types — alumni, current students, corporate guests — each seeing different instructions; plus a waitlist.
How Seats Get Deducted
Version one was too naive: a remaining count per session, minus 1 on each successful registration. In testing, two people clicked the last seat simultaneously and both succeeded. The old check-then-write problem again.
As with the fresh-produce project, we handed the decision to the database:
UPDATE sessions SET seats = seats - 1 WHERE id = <session> AND seats > 0
The backend checks rowCount; 0 means the waitlist. Waitlisted entries take no seats and queue by submission time — when someone cancels, a scheduled job picks the first in line and emails them to confirm within 24 hours. That "confirm before promoting" step was the client's idea, in case waitlisted people had long forgotten.
The Attendee-Type Wrinkle
The three attendee types started as one mandatory dropdown. The backend data then showed a batch of people choosing "Other," with "alumni family member" written in the remarks. The client said those people actually belong under corporate guests. We didn't change the options — we changed the copy, adding a line of fine print beside the dropdown explaining how family members should choose. "Other" thinned out after that.
The Export Was Harder Than the Page
The day before the event, the program team wanted rosters. Not one master sheet — 6 sheets by session, each sorted by attendee type with phone numbers and organizations, printed for the check-in desk. We wrote an export script in PHP generating an xls, one sheet per session with a fixed 7-column header. Version one forgot to list waitlisted people separately; the check-in desk nearly missed someone. We added a "waitlist" sheet.
Since then, for export formats we always ask the other side for a sample they've used before and follow it — we don't design our own.
Launch Day
It opened at 10 a.m. on July 20. A few of us refreshed the per-session remaining counts in the admin — 100-plus registrations in the first 20 minutes, with session 3 the fastest, full in 40 minutes and pushing people to the waitlist. One small episode: someone registered for two sessions with the same phone number. Support called; the person wanted to attend both talks. The rules didn't allow it, so the backend merged them, keeping one.
By midday, 4 of the 6 sessions were full. We left the rest alone — the page kept running by itself.

