Concurrency
Two people, one slot. Only one booking.
With over a million bookings processed, NeetoCal must handle situations where two visitors attempt to book the same time slot simultaneously. Both requests might pass application-level validations, but only one should succeed. The situation becomes even more complicated when payments are involved.
- The database has the final say. We use PostgreSQL exclusion constraints to prevent overlapping bookings at the database level. Even if two requests pass the Rails validations simultaneously, the database ensures that conflicting bookings cannot both be saved.
- Deadlocks, handled gracefully. Concurrent database operations can sometimes result in deadlocks. NeetoCal handles these failures and informs the visitor that the selected slot is no longer available, rather than displaying an unexpected error.
- Payments without double bookings. If a customer completes a payment but loses the race for the booking, we give them 10 hours to select another time slot. If they don’t, we automatically issue a refund. The refund process is idempotent, preventing duplicate refunds if a job is retried.
- Row-level locking where it matters. We use database row locks to protect shared resources such as group booking capacity, discount-code usage limits, and saved-card payment operations. This prevents concurrent requests from exceeding limits or processing conflicting operations.
What you getEngineers who understand concurrency and know when correctness must be enforced at the database level. These principles apply beyond scheduling to inventory management, ticketing, payments, and any application where multiple users compete for limited resources.
exclusion_constraint "user_id WITH =, is_overridden WITH =, tsrange(starts_at, ends_at) WITH &&", using: :gist, name: "booking_slot_should_not_overlap"
The rule lives in Postgres, so it holds everywhere.