Double booking is rejected by the database
What we did
Availability is stored as `tstzrange` with a GiST exclusion constraint on (listing_id, period).
Why
Application-level checks are a race waiting to happen: two requests both read 'free', both write. An exclusion constraint makes overlapping ranges impossible to commit, whatever the application does.
What it cost
Sub-hour granularity gets awkward, so bookings are capped at one-hour resolution. For equipment hire that is the right trade; for a meeting-room product it would not be.