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.

Frequently asked

How do I check whether a time slot is available in RUAL?

Query the resource's bookings overlapping the requested window with two range filters on the same query: start < requested_end AND end > requested_start. No overlaps means the slot is free, and any overlaps are returned so the UI can show why.

How do I prevent double-bookings in RUAL?

Re-check the overlap inside the reservation flow, never trusting the page's earlier check, then create the booking with a status transition inside one mutation set. Mutations process sequentially per document, so the check and the write cannot interleave, and on conflict you reply 409 with the overlapping booking.

How do I send booking reminders in RUAL?

Run a schedule_repeating_event hourly that queries confirmed bookings starting within the next 24 hours where reminder_sent is false, send each one, then set reminder_sent = true. The marker keeps the job idempotent even if a run repeats.