How an RSVP gets confirmed
A guest goes from “I’d like to come” to “I have a seat” in one step, and that one step has to be airtight. There are three ways a guest gets onto the list: they fill the web form, they reply to your invite email, or the host imports a batch of names. All three end at the same place — a request for a seat. And that request is granted by a single, careful database write that makes overselling impossible, even when two people reach for the last seat in the same second.
Key takeaways
- Three sign-up lanes feed one list: the web form, an email reply, and a host import.
- A new sign-up is checked for duplicates so nobody double-books a seat.
- A seat is claimed by a single conditional write — it only succeeds if the event isn’t full.
- If the event is full, the person is placed on the waitlist and told their position.
- The capacity cap is defended by the database, not by hopeful counting in code.
Three lanes onto one list
Lane 1: the web form
The simplest lane. The register page asks for a name and email and posts to a Function URL — a plain web address that runs a small Lambda, with no API Gateway in front of it. The Lambda first checks whether this email is already on the list: if it is, the guest just gets their existing status back (“you’re already confirmed” or “you’re number 4 on the waitlist”) instead of a second row. If it’s a new email, the Lambda asks the guest-list keeper for a seat. Most guests come in this way.
The form itself is static — it can sit on any page you already have. There’s no login, no account to create. The whole interaction is: type two fields, click, get an email. That low friction is the point; the easier it is to RSVP, the more accurate your headcount.
Lane 2: the email reply
Plenty of people will just reply “yes, count me in” to your invite rather than click a form. Lane 2 catches them. Set up a dedicated inbound address through Amazon SES — something like rsvp@your-event.com. When a reply lands, SES writes the raw message to S3, which triggers a small parser Lambda. The parser reads the sender’s name and email from the message headers and runs the same seat request the form would. A short confirmation (or waitlist notice) goes back to the same address.
The parser keeps it deliberately simple: it only needs the name and email, both of which are in the message envelope. It does not try to interpret the body for clever intent — a reply to the RSVP address is the intent. If someone replies to cancel instead, the body is scanned for a clear “cancel” or “can’t make it,” and on a match the guest is routed to the cancel flow from Part 4 rather than a sign-up.
Lane 3: host import
Sometimes the host already has the list — a team roster, last year’s attendees, a sheet of names collected at a previous event. Forcing all of them to fill a form would be silly. Lane 3 lets the host paste a list of names and emails. An import Lambda walks the list and runs the same seat request for each person. The host chooses whether the imported guests are placed as pending (they still get an invite and have to confirm) or pre-confirmed (they’re straight onto the seat, useful for a guaranteed VIP list).
Even on a bulk import, every single person still goes through the same conditional write. If the import would push past the cap, the people beyond the cap land on the waitlist in list order — the import can’t sneak past the capacity limit any more than a single sign-up can.
The one write that defends the cap
Here is the heart of the whole system. Granting a seat is not “read the count, check it’s under the cap, then add one.” That two-step approach has a gap: two sign-ups can both read “39 of 40” at the same instant, both decide there’s room, and both write — and now you have 41 confirmed for a 40-seat room. Instead, the keeper claims a seat with a single conditional write: one database update that says “increase the confirmed count by one, but only if it’s currently below 40.” The database runs that check and the increase as one indivisible step. If two writes race, exactly one succeeds and the other is refused. The loser isn’t an error — they’re simply placed on the waitlist instead.
This is why the cap can be trusted absolutely. There is no moment where the count is read separately from being changed. The number of confirmed guests is never wrong, never even briefly over the cap, no matter how many people click at once.
What the guest sees
From the guest’s side, none of this is visible. They sign up and within a second or two they get one of two emails. Confirmed: “You’re in — here are the details, and a link to cancel if your plans change.” Waitlisted: “The event is full, but you’re number 3 in line. If a seat frees up we’ll email you a link to claim it.” Both are clear, both set the right expectation, and both contain the links the rest of the system needs.
Next post: how the system schedules each confirmed guest’s reminders — a week out, a day out, the morning of — and how quiet hours keep any of them from landing in the middle of the night.
All posts