How a cancellation frees a spot
A guest can’t make it, so they click “cancel” in their confirmation email. That one click has to do four things in the right order: prove it’s really them, hand back the seat, stop the reminders they no longer need, and offer the freed seat to the waitlist. Do any of them wrong and you get an empty seat that should have been filled, a reminder to someone who isn’t coming, or a headcount that no longer adds up. Four small steps sit between the click and a clean cancellation.
Key takeaways
- The cancel link carries a signed token, so only the real guest can cancel their seat.
- Releasing the seat is a conditional write that lowers the confirmed count by one.
- The guest’s pending reminder jobs are deleted so they never get a stale reminder.
- A freed seat immediately kicks off the waitlist offer covered in the next post.
- Every step is logged, so the live headcount is always exactly right.
Four steps on every cancellation
Step 1: verify the token
The cancel link in every confirmation email isn’t a plain web address — it carries a signed token, a short string the system created and signed when the guest confirmed. The token identifies exactly which seat the link belongs to, and the signature proves the system made it. When the link is clicked, the cancel Lambda checks the signature before doing anything else. A tampered or guessed link fails the check and is rejected. This keeps one guest from cancelling another’s seat just by editing a web address, and it means the cancel flow needs no login — the signed link is the proof of identity.
Tokens are scoped to the event and have a sensible lifetime (they stop working once the event has passed). A guest who lost their email can ask the host to re-send the link, which mints a fresh token for the same seat.
Step 2: release the seat
Handing the seat back is the mirror image of claiming it. Just as a seat was granted by a conditional write that only succeeded if the event wasn’t full, releasing it is a conditional write that only succeeds if the guest is actually still confirmed. That condition matters: if the guest clicks the cancel link twice (or clicks it, then the page reloads and fires again), the second attempt finds the guest already cancelled and does nothing. The confirmed count drops by exactly one, never two. The cap defends itself going down just as it does going up.
The guest’s state moves to cancelled. Their row stays on the list — nothing is deleted — so the audit trail and the headcount history stay intact. They simply no longer hold a seat.
Step 3: cancel the reminders
Back in Part 3, the moment this guest confirmed, the system booked their reminders as one-off Scheduler jobs and recorded the job names against the guest. Step 3 reads those job names and deletes each one. This is the step people forget, and it’s the one guests notice most: nothing looks worse than getting a cheerful “See you tomorrow!” reminder the day after you cancelled. Because each reminder is its own named job, cleanup is exact — the system deletes precisely this guest’s jobs and touches no one else’s.
If a reminder job has already fired (the week-out reminder went out before the guest cancelled), there’s nothing to delete for that one — it’s already done. Only the still-pending jobs are removed.
Step 4: kick off the waitlist
A freed seat is no good if it just sits empty. The final step emits a small “seat freed” event that starts the waitlist offer — the subject of the next post. The cancel flow itself doesn’t pick the next guest or send the offer; it just announces that a seat is open and lets the waitlist logic take over. Keeping the two flows separate means a cancellation is fast and simple, and the waitlist offer (which has its own timing and claim window) runs on its own.
One small but important detail: the seat-freed event fires only if a seat was genuinely released in Step 2. A double-clicked cancel that did nothing the second time doesn’t fire a second waitlist offer. One freed seat, one offer.
Why this order, and why it’s logged
The order is deliberate: verify before changing anything, release the seat before announcing it’s free, clean up reminders so the cancelled guest goes quiet, and only then hand the seat onward. Every step writes a row to the ev-audit table — who cancelled, when, which seat, and what the count went from and to. After the event, the host can reconstruct the entire guest list: who confirmed, who cancelled, when each seat changed hands. The live headcount the host watches is just the current state of this same data, so it’s never out of sync with reality.
Next post: how that freed seat finds the next guest — the timed waitlist offer, the claim window, and what happens when an offer goes unclaimed.
All posts