Sajjad Mahessar Good Merch Group Free audit
~/sajjad $ cat projects/function-booking ← cd ../projects Systems

Function room booking & pricing

Live · Oct 2026Priced by date

A public booking page for a venue’s function room. The customer picks a date, fills in the event details and pays by card, at a price set by the date. The date is held for five minutes while they pay, and the booking only exists once the payment provider confirms the money arrived.

Type
Booking system
Category
Systems
Built with
Supabase Edge Functions · Stripe Checkout · Webhooks · Netlify
Project
12 of 37
A DATE CAN’T BE SOLD TWICE PICK DATEblocked dates hidden 5-MIN HOLDdate reserved CHECKOUTdeposit by card SIGNEDwebhook BOOKING CONFIRMED THE PAGE NEVER HOLDS A DATABASE KEY ONE FUNCTION IS THE ONLY THING IT CAN TALK TO
The booking exists only once the payment provider says it’s paid

How a booking happens

  • The page asks for availability and gets back the deposit, the booking window and the dates that can’t be booked — nothing else.
  • Submitting places a five-minute hold on the date and opens a card checkout for the deposit.
  • The booking is not confirmed when the customer clicks pay. It’s confirmed when the payment provider’s signed webhook says the money arrived.

Why it’s built that way

Two failure modes matter for a function room: two families paying for the same Saturday, and a booking that exists without a deposit behind it. The hold closes the first; confirming only on the signed webhook closes the second, because a browser redirect can be faked and a closed tab never arrives.

Same pattern as the QR system next door: the public page talks to one server function and never sees a database key, and it shares that venue’s existing payment account rather than opening another one.

Moved to dynamic pricing

  • Moved from a flat deposit to full payment up front, priced by the date: one price Sunday to Thursday, a higher one on Friday and Saturday, and a peak price from a peak-dates table (December weekends, Christmas Eve, bank holiday weekends). There’s a 14-day full-refund cancellation window.
  • Prices were set after researching comparable social clubs in the area. The calendar doesn’t show prices; they appear once a date is picked, and the server, not the page, works out the amount charged.
  • New database functions for pricing and the full-payment hold, a rewritten booking function, and an end-to-end test booking before going live.

What went wrong

The payment provider warned that the booking webhook was failing every delivery with “Bad signature”. The timing pointed to the cause: setting up the ticketing system’s webhooks had overwritten the booking function’s signing secret.

The booking function’s correct secret went back in and the failed events were replayed, so paid bookings that had been left unconfirmed went through without anyone paying twice. The signature check did its job: it rejected everything rather than accepting an unverified payment.
Payments platform

QR ordering, rebuilt hardened for a second venue

Second venue, rebuilt to pass 49 attacks

SupabaseNetlify FunctionsStripebcrypt
Booking system

Table booking system

In-house reservations, 395 bookings migrated

PostgreSQL/SupabaseEdge FunctionsDatabase webhooksRLS
No charge

I’ll find the money before you pay me anything.

Send me your software subscriptions and I’ll come back with what’s replaceable and what it’s worth — free, and yours to keep either way. How it works →

Contact

Want the same done to your cost base?

Open to operations, automation and technical operations roles — and to talking with anyone running a multi-site business who suspects they're paying for software they could own instead.