Overview / Bookings
ADR 0044
Bookings are a thin vertical over the commerce catalog, not a standalone scheduler
AcceptedBookings
Context
Inkress serves not only retail merchants but service businesses that take appointments. The choice was whether to build a standalone scheduling product (its own domain: services, clients, locations, staff availability, waitlists, blocked slots, a public booking site) or to reuse the existing commerce core (catalog, checkout, payments, tenancy) for bookings.
Decision
Model bookings as a thin vertical over the commerce catalog: a booking is a time-boxed reservation of a product variant, not a new standalone entity.
- A service is a product variant.
Booking belongs_to :variant(a required product variant), so a bookable service is just a catalog item with a time box; staff are attached viaBookingAttendantand changes tracked inBookingHistory. - Reuse the core. Bookings inherit checkout, payments, the order model (ADR 0034), tenancy (ADR 0020), discounts and generic CRUD from the commerce platform rather than a parallel stack.
- A fuller standalone scheduler also exists — in commerce-worker, on its own database. commerce-worker carries a separate appointment system: its own
Api.Main.Repowithappointments,waitlist_entriesandblocked_slotsmigrations plus providers/clients/services/locations schemas and context. It is built but is not the commerce-integrated path — it does not ride the commerce checkout/order pipeline, and its public/book/:slugweb layer is absent. So the two models coexist: the thin variant-reservation booking is the one wired into commerce; the standalone scheduler is a parallel subsystem.
Consequences
- Positive: one platform serves retail and bookings; a booking flows through the same checkout, payment, discount and order machinery for free — no second commerce stack to maintain.
- Neutral / to revisit: modeling a service as a product variant keeps true scheduling concepts (staff availability windows, locations, waitlists, blocked slots) thin or absent. Businesses needing rich scheduling would outgrow the variant-reservation model, which is where the (deferred) standalone design would return.
- Neutral / to revisit: two booking models coexist — the thin variant-reservation one (commerce-api, rides checkout/payments) and the fuller standalone scheduler (commerce-worker, its own
Api.Main.Repo, missing only the public web layer). Which one a new feature should build on is not unified; consolidating or clearly delineating them is open.
Alternatives considered
- A standalone appointment/scheduling system: actually built in commerce-worker (its own DB: appointments/waitlist/blocked-slots), but not wired into the commerce checkout/order pipeline and missing its public web layer — so the thin catalog-vertical remains the commerce-integrated booking path. The two coexist rather than one being rejected; the thin vertical is preferred for anything that must ride checkout/payments.
- A separate "bookings" product distinct from catalog items: rejected — making a service a product variant lets bookings ride the entire existing commerce pipeline without new plumbing.