# 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 `Performance` row. - 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.