Part 5 of 7 · Event RSVP manager series ~5 min read

How a freed spot finds the next guest

A seat just opened and three people are waiting for it. The fair, safe way to fill it isn’t to grab the first waitlister and confirm them — they might have made other plans. It’s to offer the seat, hold it for them for a set window, and move on if they don’t take it. This post walks through the waitlist offer: who gets it, how long the seat is held, and the three things that can happen — the offer is claimed, the window lapses and the offer rolls on, or the waitlist is empty and the seat waits.

Key takeaways

  • A freed seat is offered to the first person on the waitlist, not silently given to them.
  • The offer holds the seat for a claim window (default 6 hours) via a one-off Scheduler timeout.
  • If the offer is claimed, a conditional write moves the guest into the confirmed seat.
  • If the window lapses, the offer rolls to the next person automatically — nobody is skipped.
  • If the waitlist is empty, the seat simply stays open for a new sign-up.

Three outcomes of a waitlist offer

Three outcomes of a waitlist offer A diagram showing one input on the left flowing through a waitlist offer, then branching into three outcome paths. Far left: a "Seat freed" box showing the seat-freed event from a cancellation — it names the open seat and the front of the waitlist, and shows the offer being emailed to the first person in line with a claim link and a deadline. A one-off EventBridge Scheduler timeout is booked for the end of the claim window. The middle column shows the three branches. Branch one, Claimed: the waitlister clicks the claim link before the window closes; a Function URL Lambda runs a conditional write that moves them from waitlisted to confirmed and keeps the confirmed count correct, books their reminders, deletes the pending timeout, and sends a confirmation. Branch two, Window lapsed: the claim window ends with no click; the timeout fires, the offer is marked expired, and the seat-freed event is re-emitted so the offer rolls to the next person on the waitlist automatically. Branch three, Waitlist empty: there is nobody in line; the seat is simply left open for a fresh sign-up, and the host headcount shows one open seat. The right side shows the convergence: every outcome writes a row to the ev-audit DynamoDB table with timestamp, seat, action, who, and notes. A note at the bottom: a freed seat is offered, not given — a stale offer rolls on, and the seat is never blocked forever. Seat freed offer to first in line [Claim link] [Deadline set] [Timeout booked] Outcome 1 Claimed • Clicks before window ends • Conditional write → confirmed • Reminders booked • Timeout deleted Outcome 2 Window lapsed • No click; timeout fires at the deadline • Offer marked expired, rolls to the next in line Outcome 3 Waitlist empty • Nobody in line to offer it to • Seat stays open — ready for a sign-up Audit trail DynamoDB ev-audit timestamp · seat action · who notes A freed seat is offered, not given — a stale offer rolls on, and the seat is never blocked forever.
Fig 5. Three outcomes of a waitlist offer. Claimed moves the guest into the seat. A lapsed window rolls the offer to the next person. An empty waitlist leaves the seat open. Every outcome writes to the audit trail.

The offer, not the grant

The most important design choice in the whole waitlist is that a freed seat is offered, not handed over. If the system simply confirmed the first waitlister the moment a seat opened, you’d end up confirming people who’ve already made other plans — and then chasing their cancellation. Instead, the first person in line gets an email: “A seat just opened. Click here to claim it — this offer holds your seat until 4pm today.” The seat is reserved for them and only them until the deadline. They’re in control, and the host doesn’t end up with a confirmed guest who never wanted the seat.

When the offer goes out, the system books a one-off timeout job through EventBridge Scheduler set to the end of the claim window (six hours later by default). That timeout is the safety net that guarantees the seat never gets stuck on someone who isn’t going to respond.

Outcome 1: the offer is claimed

The happy path. The waitlister clicks the claim link before the window closes. A Function URL Lambda runs a conditional write that moves them from waitlisted to confirmed — the same careful, indivisible update that grants a seat in the first place, so even here the cap can’t be exceeded. Their reminders are booked exactly as a normal confirmation’s would be (the flow from Part 3). The pending timeout job is deleted, since the offer resolved before it needed to fire. And a confirmation email goes out: “You’re in — here are the details.” From the guest’s side, claiming a waitlist seat feels exactly like a normal confirmation.

Outcome 2: the window lapses

The waitlister never opens the email, or opens it too late. At the deadline, the timeout job fires. It first checks whether the offer was already claimed — if it was, there’s nothing to do. If it’s still outstanding, the offer is marked expired and the system re-emits the same “seat freed” event that started everything. That re-emission hands the seat to the next person on the waitlist, who gets their own fresh offer with their own six-hour window. The seat rolls down the line, one person at a time, until someone claims it or the list runs out. Nobody is silently skipped; everyone gets a real chance at the seat in turn.

This rolling behavior is why the offer-not-grant model is safe: a waitlister who’s gone quiet can’t block the seat forever. After their window, it simply moves on.

Outcome 3: the waitlist is empty

Sometimes a seat frees up and there’s nobody waiting — the event filled, then someone cancelled, but no one ever joined the waitlist. In that case there’s no one to offer the seat to, so the system does the simplest thing: it leaves the seat open. The confirmed count is already lowered (that happened when the seat was released), so the next person to hit the register form will find room and get confirmed straight away through the normal flow from Part 2. The host’s live headcount just shows one open seat until someone takes it.

Quiet hours and the one edge case

Waitlist offers respect quiet hours like any other message — an offer that would land at midnight is normally held until morning. But there’s a deliberate exception. If holding the offer until morning would mean the claim window closes before a reasonable person could act — the event is tomorrow and the seat needs filling tonight — a host setting can let time-critical offers through the quiet window. The reasoning is simple: a late-night email is a small annoyance, but a seat that goes empty because the offer waited politely until 8am is a real loss. The host chooses which matters more for their event.

Every offer, claim, expiry, and roll-on writes a row to ev-audit. After the event, the host can see the full story of any seat: who held it, who cancelled, who was offered it, who let it lapse, and who finally took it.

Next post: the cost breakdown. The whole system above runs in coffee-money territory per event; Part 6 explains exactly where the dollars go and why most of the bill is just the emails.

All posts