Back to work

MauApa Booking API

Booking and live queue API for barbershops, built around one guarantee.

0 double bookings 2026

The live queue board at /app
The live queue board at /app

Overview

Two customers message a barbershop at the same time asking for the 10:00 slot with the same barber. Whoever the owner replies to first gets it, and often both do, because the owner reads both messages at 10:05. Slot maths, the queue and the dashboard are ordinary CRUD by comparison. The two requirements that actually matter are that simultaneous bookings for one staff member must never both succeed, and that one shop must never see another shop's data.

Check-then-insert cannot deliver the first one. Between the check and the insert there is a window, and the row that must not exist yet cannot be locked, so SELECT FOR UPDATE has nothing to take a lock on. The rule therefore lives in the database as a GiST exclusion constraint over staff id and a half-open time range, made partial so a cancelled booking releases its slot. Running it surfaced a second problem: conflicting inserters wait on each other and Postgres kills the resulting cycle. Across forty rounds of three concurrent bookings, 60 requests died as deadlocks rather than honest conflicts.

Key features

The database holds the rule

An exclusion constraint rejects overlapping bookings regardless of interleaving. The application's only job is translating that rejection into a 409.

Advisory lock kills the deadlocks

A transaction-scoped lock per staff member turned 60 deadlocks into 0 across the same forty rounds, while bookings for different staff still run in parallel.

Unowned shops answer 404

A 403 would confirm the id exists and hand anyone probing ids a free oracle, so another tenant's shop is indistinguishable from one that was never created.

Queue broadcasts over Redis

Socket.IO rooms are keyed per shop and published through Redis pub/sub, so the live queue keeps working once the API runs more than one instance.

Screens

Swagger documenting every endpoint, with the double-booking and tenancy rules stated up front
Swagger documenting every endpoint, with the double-booking and tenancy rules stated up front
The customer booking page, with unavailable slots computed and disabled
The customer booking page, with unavailable slots computed and disabled
Feature overview and the four-step setup flow
Feature overview and the four-step setup flow