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": {
    "cms": 1782166695442,
    "created": 1782166695,
    "entity": 1,
    "expiry": -1,
    "guid": "e67919283b4e37c9758326446605ab863bf452cda26f91c2aef74ba31f9a3214",
    "removed": 0,
    "ums": 1782170295118,
    "update_hash": "7b25e0af9163c4d8052ae7f31964bc0d8a5f3c62",
    "updated": 1782170295
  },
  "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.