Series · 7 parts Published June 7, 2026

Waitlist manager

A serverless system that turns no-shows and cancellations into filled slots. For a business that books slots — a salon, a clinic, a restaurant — it keeps a waitlist; when a slot frees up, it offers that slot to the next suitable person on the list with a short claim window, rolls to the next if they don’t take it, and confirms the booking. Fair order; no double-booking. Seven posts on the same system — one diagram at a time — with an engineering reference at the end.

  1. 01

    A waitlist manager on AWS for a few dollars a month

    The whole system on one page — a waitlist intake, an offer engine, and a sender, plus the four moves they share for every freed slot.

  2. 02

    How a waitlist entry gets added

    Three lanes feed the list — the Drive sheet itself, an inbox-forwarding lane that parses booking requests into proposed rows for one-tap approval, and a web form that drops new entries straight in.

  3. 03

    How a freed slot gets noticed

    A cancellation, a no-show, or a new opening comes in; the engine finds who on the list actually fits the slot, sorts them in fair order, and picks one of four moves: nobody fits, make an offer, roll on, or hand back to staff. No model in the loop.

  4. 04

    How an offer reaches the next person

    Picking the next eligible entry, quiet hours, a text or email with a one-tap claim link and a countdown, and the four guardrails between the engine’s chosen move and the offer actually landing.

  5. 05

    How a slot gets claimed or rolls on

    One conditional write decides it: the first valid claim books the slot, any later click is told it’s taken. If the window ends unclaimed, the offer rolls to the next person. Decline, claim, and time-out are all logged.

  6. 06

    What the waitlist manager costs

    A couple of dollars a month at SMB volume. The engine wakes only when a slot frees up, calls no models on the offer path, and only fires Bedrock on the inbound parsing lane and the monthly summary.

  7. 07

    Engineering reference: the waitlist manager architecture

    Same system, drawn purely for engineers. Service names, resource identifiers, region, Bedrock model IDs, Lambda inventory, IAM scopes, the SES inbound rule set, EventBridge Scheduler config, the conditional-write claim, and the DynamoDB schemas.

What is a waitlist manager?
A small serverless system for a business that books slots — a salon chair, a clinic appointment, a restaurant table. It keeps a waitlist of people who want an earlier time. When a slot frees up (a cancellation or a no-show), it offers that slot to the next suitable person with a short claim window. If they don’t take it in time, the offer rolls to the next person. When someone claims it, the booking is confirmed. Fair order, and never two people booked into the same slot.
How much does it cost to run?
About $2/month at typical small-business volume (around 200 waitlist entries a month). The fixed cost is essentially zero. The variable cost is dominated by the offer texts and emails and a small daily housekeeping tick; Bedrock and Textract fire only on the inbound parsing lane and the monthly summary, so they’re small slivers. At 2,000 entries a month the bill lands around $13.
Which AWS services does it use?
Lambda (Python 3.14, arm64) with Function URLs for the claim links, EventBridge Scheduler for claim-window timers and the daily housekeeping tick, DynamoDB on-demand (with a conditional write that guarantees no double-booking), S3 (with versioning), SES inbound + outbound, SNS for text messages, SQS with a dead-letter queue, Secrets Manager, CloudWatch Logs (7-day retention), AWS Budgets, and Bedrock (Claude Haiku 4.5 via Global cross-Region inference) for the inbound parsing and monthly summary. No API Gateway, no NAT Gateway, no always-on compute.
Where does the waitlist live?
In a Google Sheet in a Drive folder. One row per entry with name, contact, the service or table wanted, party size, the earliest and latest dates that work, any staff preference, a priority flag, and the time they joined. A small drive-sync Lambda mirrors the sheet to S3 every few minutes; the offer engine reads from S3 to keep Drive calls predictable and to get S3 versioning for free.
How does it pick who gets the offer first?
The rules doc holds the order. By default it’s first-come, first-served by join time, but only among entries that actually fit the freed slot — right service, right party size, the date inside their window, and a matching staff preference if they set one. A priority flag (a VIP, or someone bumped by a previous cancellation) can move an entry up. The order is written down and the same every time, so nobody jumps the queue by accident.
What stops two people getting the same slot?
Only one offer is live for a slot at a time, and claiming uses a single conditional write to DynamoDB that succeeds for exactly one person. The first valid claim flips the slot to booked; any later click sees it’s already taken and gets a polite “this slot was just filled” message. The claim link also carries a short-lived token tied to that one offer, so an old link can’t book a slot that has already rolled on.
What happens if nobody claims the slot?
Each offer has a short claim window (default 10 minutes, set per business). An EventBridge Scheduler timer fires when the window ends. If the slot is still open, the offer rolls to the next suitable person and a fresh window starts. This repeats down the list. If the list runs out, the slot is handed back to staff with a note. Every offer, claim, and roll is logged in the wl-audit DynamoDB table, so the trail is auditable later.
All posts