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

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

Four steps between a cancel click and a clean cancellation A horizontal flow diagram. On the far left, a "Cancel clicked" box: the guest tapped the cancel link in their confirmation email, which carries a signed token identifying their seat. Four step gates sit in a row to the right, each drawn as a vertical bar. Gate 1: Verify token — checks the signed token on the cancel link so only the real guest can release their own seat; an invalid or expired token is rejected. Gate 2: Release seat — a conditional write to the guest-list keeper sets the guest's state to cancelled and lowers the confirmed count by one, but only if they were actually confirmed, so a double-click can't lower the count twice. Gate 3: Cancel reminders — looks up the guest's booked reminder jobs in DynamoDB and deletes each one-off EventBridge Scheduler rule, so a cancelled guest never gets a stale "see you tomorrow" reminder. Gate 4: Kick off waitlist — emits a seat-freed event that starts the waitlist offer covered in the next post, handing the open seat to the first person in line. After all four steps, a short cancellation acknowledgment goes back to the guest, and the freed seat is on its way to the waitlist. A note at the bottom: every step is logged to the audit table so the live headcount always adds up. Cancel clicked signed link from confirm email Step 1 Verify token signed token on the link? matches seat? reject if invalid Step 2 Release seat conditional write to keeper count − 1 if still confirmed Step 3 Cancel reminders find booked reminder jobs delete each Scheduler rule Step 4 Kick off waitlist emit a seat-freed event offer goes to the next in line Clean cancellation — guest told, seat freed, reminders gone acknowledgment email to the guest · seat-freed event to the waitlist every step logged to ev-audit — the headcount always adds up Every step is a deterministic check — no model calls, no guessing who freed which seat.
Fig 4. Four steps between a cancel click and a clean cancellation. Verify the token. Release the seat. Cancel the reminders. Kick off the waitlist. Then tell the guest and log every step so the headcount always adds up.

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