Skip to main content
Help centre
Bookings

What happens when a member tries to double-book?

Conflicting bookings can't reach the database. The check happens at the SQL level, not just the UI, so a fast finger or a janky network can't slip a duplicate through.

2 min read·Updated 2026-05-01

The mechanic

Every court has a unique constraint on (court_id, time_range). When the database sees two bookings whose ranges overlap on the same court, the second insert is rejected. The UI then translates that error into a friendly message — "That slot was taken about a second ago" — and refreshes the grid so the member sees the actual state of the world.

What the member sees

On their booking page, the slot greys out with a small "just booked" tag. They can pick another slot. If they were halfway through Stripe checkout when the conflict happened, the payment intent is voided automatically — no double charge, no manual refund.

What the audit log records

The successful booking lands in the audit log as booking.create. The failed attempt is logged at debug level (visible in the dashboard's diagnostics tab but not in the public audit log). If you suspect abuse — a member spamming bookings to deny others — both the success and failure are visible to staff.

Edge cases

  • Back-to-back times. A booking from 10:00–11:00 doesn't conflict with one starting at 11:00 — the constraint uses half-open intervals.
  • Tournament blocks. Treated as a booking; members can't book through one.
  • Maintenance closes. Same — the close is a system booking on the court.
  • Time zone drift. All bookings are stored in UTC and rendered in the club's configured time zone. Members travelling abroad still see the right slot.

Did this help?

If anything's missing or wrong, email us — we update articles when readers point things out.

Email feedback