How a waitlist entry gets added
The engine can only offer a slot to someone who’s actually on the list. So the first job is making sure the list reflects everyone who wants an earlier time. There are three ways an entry gets in: a staffer types a row in the Drive list, somebody forwards a booking request to a dedicated address, or a customer fills in a short web form. The first one is obvious. The other two exist because in real life nobody stops mid-shift to type a row for the person standing at the desk asking to be called if anything opens up.
Key takeaways
- Three intake lanes feed one waitlist: the Drive list, an inbox-forwarding lane, and a web form.
- Forwarded requests are parsed by Textract; Bedrock Haiku 4.5 reads the text and proposes a row.
- Every parsed row goes to a staffer for one-tap approval before it lands in the list.
- The web form writes a clean row directly — it’s already structured, so there’s nothing to parse.
- The Drive list stays the canonical store. The other lanes are conveniences that write into it.
Three lanes into one list
Lane 1: the Drive list itself
The simplest lane. Open the waitlist sheet in Drive, add a row, save. The columns are short: 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 Lambda — drive-sync — runs every few minutes, exports the sheet as plain CSV via the Drive API, and writes it to s3://wl-waitlist-source/waitlist.csv if the sheet has changed since the last sync. The engine reads from S3, not Drive directly. That keeps Drive calls predictable and gives you S3 versioning for free, so a bad bulk-edit can be rolled back in one click.
This lane covers the front-desk case: a customer rings or walks in, asks to be called if anything opens, and a staffer has thirty seconds to type it in. It’s also how staff fix a row — change someone’s date window, bump a priority flag, or take a person off the list once they’ve been booked.
Lane 2: inbox forwarding (the lane for messy requests)
Set up a dedicated inbound address — something like waitlist@your-business.com — via Amazon SES. When a request comes in by email (a customer writes “can you call me if a Saturday colour opens up?”, or a booking-site notification lands), a staffer forwards it to that address and the system takes it from there. SES writes the raw message to s3://wl-raw-mime/. The S3 write triggers a parser Lambda. The Lambda walks the message to any attachment, runs Amazon Textract on it if it’s a PDF or image (Textract reads PDF, PNG, JPEG, and TIFF natively), and otherwise just reads the email body text.
Then a Bedrock Haiku 4.5 call reads the text and emits a structured row: name, contact, service, party size, the earliest and latest dates that work, and any staff preference mentioned. The model prompt is short: “Extract a waitlist entry. Return JSON only. Mark each field with a confidence score. Do not invent a date that isn’t in the text.” The output goes to a small interactive message on the staffer’s phone: the proposed row, the confidence per field, and three buttons — approve, edit, discard. On approve, a Lambda writes the row to the Drive list via the Sheets API. On edit, the staffer gets a fillable form pre-populated with the proposal. On discard, the message is logged and the raw email moved to a discarded prefix in S3 for audit.
The reason every parsed row goes to a human first is simple: an entry the model misread is worse than one that never made it onto the list. A wrong phone number or a wrong date means an offer that can’t be honored — and the whole point of the system is that every offer is real.
Lane 3: the web form
The lowest-effort lane for the customer, and the one that scales without any staff time at all. A simple hosted page — “Join the waitlist” — collects the same fields: name, contact, service, party size, the date range that works, and an optional staff preference. The page posts to a Lambda Function URL. The Lambda validates the fields (a real phone number or email, a sensible date range, a service that exists), drops obvious spam, and writes a clean row straight to the Drive list via the Sheets API. Because the form already collects structured fields, there’s nothing to parse and no approval step — the row is good the moment it’s submitted.
Put the form link on your booking confirmation page (“Want an earlier time? Join the waitlist”), in your booking emails, and on your social profiles. It turns “we’re fully booked” from a dead end into a captured lead.
Why the list stays the source of truth
Three lanes in, but only one place the engine actually reads. That’s a deliberate constraint. If two lanes both wrote directly to the engine’s state, every “why did this person get offered the slot?” question would mean checking three places. Funneling everything through the Drive list means there is exactly one row per entry, and any staffer can read or edit any of it without learning a new tool. The convenience lanes are first-class for getting entries in, but they always pass through the list on the way.
Next post: how the engine notices the moment a slot frees up, works out who on the list actually fits it, and picks one of four moves.
All posts