1.3 KiB
ADR-0005: Prevent Overbooking with Database Transactions
Date: 2026-04-28
Status
Accepted
Context
AzioneLab allows multiple visitors to create pending reservations for the same performance. Pending reservations do not guarantee seats, so final capacity must be enforced when a reservation is confirmed.
Concurrent confirmation requests could otherwise read the same availability and confirm more seats than the performance allows.
Decision
Use PostgreSQL transactions and Django ORM row-level locking to serialize capacity checks for a performance.
When creating or confirming a reservation, the backend locks the related Performance row with select_for_update(), recalculates confirmed seats server-side, and proceeds only if enough seats remain.
Confirmation performs the final capacity check inside the transaction before changing the reservation to confirmed and consuming the confirmation token.
Consequences
- Capacity is enforced by the backend and database, not by frontend availability values.
- Concurrent confirmations for the same performance are serialized by the locked
Performancerow. - Pending reservations can exceed current availability, but only confirmed reservations consume seats.
- The design stays simple and works with Django ORM and PostgreSQL.
- Very busy booking moments may queue briefly on the performance row lock.