Series · 7 parts Published July 5, 2026

Booking deposit collector

A no-show is the quietest way an appointment business loses money: the slot was booked, nobody came, and it was too late to sell it to anyone else. This is the design of a small serverless system that asks for a deposit the moment a booking is made — it puts a PENDING hold on the slot so it can’t be sold twice, sends one payment link in the business’s voice, and waits. Pay the deposit and a signature-verified webhook flips the booking to CONFIRMED exactly once; ignore it and a scheduled sweep quietly releases the hold so the slot can be re-sold. On the day, the deposit is applied to the bill or forfeited on a no-show, per policy. It holds a slot once, reminds once before releasing, and never double-books. Seven posts on the same system — one diagram at a time — with an engineering reference at the end.

  1. 01

    A booking deposit collector on AWS for a few dollars a month

    The whole system on one page — the booking intake that holds a slot, the deposit-request composer, the signature-verified payment webhook that confirms exactly once, the scheduled sweep that releases unpaid holds, and settlement on the day, plus the guardrail that it never double-books.

  2. 02

    How a booking requests a deposit

    How a booking becomes a held slot and a deposit request — the intake Function URL, the conditional write that holds one slot without ever double-booking, the deposit deadline, and the single Bedrock call that phrases the payment-link message.

  3. 03

    How a deposit payment gets confirmed

    How a paid deposit becomes a confirmed booking — the payment provider’s webhook on its own Function URL, verified by signature, treated idempotently, and flipping the booking to CONFIRMED exactly once with a DynamoDB conditional write even when the event arrives twice.

  4. 04

    How an unpaid hold gets released

    How an unpaid hold gets released — the EventBridge Scheduler sweep that finds bookings whose deposit deadline has passed, sends one reminder before the deadline, and releases the hold so the slot is free to re-sell, exactly once and never twice.

  5. 05

    How a no-show gets handled

    How a no-show gets handled — on the day, the confirmed deposit is either applied to the final bill for a customer who turns up or forfeited for one who doesn’t, decided by deterministic policy rather than by a model, with the outcome recorded and a human handling any dispute.

  6. 06

    What the booking deposit collector costs

    A line-by-line monthly cost at about $2.40 for roughly 120 bookings, where the money actually goes (the deposit-request texts and the small Bedrock calls that phrase them), why the payment processor’s fee isn’t on this bill, and what it all looks like at ten times the volume.

  7. 07

    Engineering reference: the booking deposit collector architecture

    The same system drawn for engineers — the two Function URLs, the Lambda inventory, the DynamoDB tables and key schema, how the slot hold and the payment confirmation are each made exactly-once, the SQS and DLQ, IAM scope, observability, and the single region.

What is a booking deposit collector?
It is a small serverless system that turns every booking into a held slot with a deposit attached. The moment a booking comes in, it writes a PENDING hold on that exact slot — so the slot can never be sold twice — and sends the customer one friendly message with a payment link. When the deposit is paid, the payment provider’s webhook flips the booking to CONFIRMED. If it isn’t paid by a deadline, a scheduled sweep releases the hold so the slot is free to re-sell. On the day, the deposit is applied to the bill or forfeited on a no-show, per the business’s policy. A booking stops being a gamble and becomes a commitment.
How much does it cost to run?
About $2.40/month at a typical volume of roughly 120 bookings a month. There is no always-on compute, so the bill is almost entirely usage-priced — the deposit-request and reminder texts and the small Bedrock call that phrases each one are the main lines, and the only real fixed cost is Secrets Manager for the payment and messaging keys. The deposit money itself flows through your payment provider, whose processing fee sits on their invoice, not this one. At ten times the volume the AWS bill lands near $15, because the fixed lines don’t move.
Which AWS services does it use?
Lambda (Python 3.14, arm64) behind two Function URLs — one for the booking intake, one for the payment webhook — DynamoDB on-demand for bookings and slot holds, EventBridge Scheduler for the unpaid-hold release and pre-appointment sweeps, SNS for SMS and SES for email, SQS with a dead-letter queue, Secrets Manager for the provider keys, CloudWatch Logs with 7-day retention, AWS Budgets, and Bedrock (Claude Haiku 4.5 via Global cross-Region inference) to phrase each message. No API Gateway, no NAT Gateway, no always-on compute. One region, eu-west-2.
How fast does it act?
Within seconds of the booking arriving, the slot is held and the deposit link is on its way — that speed is the whole point, because a deposit asked for while the customer is still keen is a deposit that gets paid. Confirmation is just as quick: the payment provider fires its webhook the instant the deposit clears, and the booking flips to CONFIRMED in the same breath. The release of an unpaid hold runs on a timer — a scheduled sweep every few minutes — because the thing it reacts to is a payment that never came.
Does it use AI?
Only to write the wording. Bedrock’s Claude Haiku 4.5 phrases the deposit-request message and the single reminder, in the business’s voice, and it is handed only the facts it may use — the customer’s name, the slot, the deposit amount — with the payment link injected by code afterwards. Every decision that touches money or the calendar is deterministic Python: placing the hold, verifying the webhook signature, flipping the booking to confirmed exactly once, releasing an unpaid hold, and applying or forfeiting the deposit. The model never decides who owes what, whether a payment is genuine, or whether a slot is free.
How does it avoid double-booking or taking a payment twice?
Two conditional writes do the heavy lifting. A slot is held with a conditional write on the slot key, so only the first booking for a given slot can take it — a second attempt fails and is offered another time, never the same one. And the payment webhook is idempotent: the confirming write is conditional on the booking still being PENDING, so if the provider delivers the same payment.succeeded event twice — which providers do — only the first one moves the booking to CONFIRMED, and the rest are acknowledged and ignored. One slot, one hold; one payment, one confirmation.
All posts