Example: Booking System

Availability, reservations, reminders, and no double-bookings — a complete scheduling app with the flow that makes conflicts impossible.

Booking looks simple until two people grab the same slot at once. This example shows the model, the conflict-proof reservation flow, and the reminder machinery.

Data Model

  • resources — what gets booked (rooms, tables, staff): name, capacity, opening hours, timezone.
  • bookings — one document per reservation:
Booking Document
{
  "_meta": {},
  "customer_guid": "b9ee6a631b24e78d1aa48aef0dc067fff7bfbacd24a56ef4ed1f08e537d48b6bd02",
  "customer_name": "sami b",
  "end": 1782364800,
  "reminder_sent": false,
  "resource_guid": "e01ff8643394371a8544d2c9f8a1b3e5d70892c4f6a0b8d1e3f5a7c9b2d4e6f8a0b2",
  "resource_name": "meeting room 2",
  "start": 1782361200,
  "status": "confirmed"
}

Resource and customer are denormalized onto the booking — calendar views show names without joins (see Storage Examples).

Checking Availability

  1. Query the resource's bookings overlapping the requested window: start < requested_end AND end > requested_start — two range filters on the same query via query_bool_range_field.
  2. No overlaps → slot is free. Overlaps → return the conflicting bookings so the UI can show why.
  3. Generate the day's available slots from opening hours minus confirmed bookings, in the function — not in the page.

No Double-Booking

  1. The reservation flow first re-checks overlap (never trust the page's earlier check).
  2. Then it creates the booking with a status transition inside one mutation set — mutations process sequentially per document, so the last check and the write can't interleave (see mutations).
  3. On conflict: reply 409 with the overlapping booking — see error conventions.
  4. Cancellation is a status change to cancelled, never a delete — the audit trail and no-show stats survive.

Reminders

  1. A schedule_repeating_event runs hourly: query confirmed bookings starting within the next 24h where reminder_sent = false.
  2. Send each with the email pattern from Email System Setup, then set reminder_sent = true — idempotent even if the run repeats.
  3. Customers manage their own bookings with user_current → term query on customer_guid.

Next Steps

Repeating Events The reminder engine's scheduler. Creating a REST API Expose availability to other apps. Inventory Tracker The same transaction discipline for stock.