Rizwanul Islam Afraim

Jan 11, 2026 • 2 min read

The "Double Booking" Nightmare: Architecture of a Safe Rental System

It’s the notification every marketplace founder dreads: "Hey, why is someone else driving the car I just booked?"

The "Double Booking" Nightmare: Architecture of a Safe Rental System

Early on with Gaari (my car rental platform), we hit a critical edge case. Two customers, miles apart, hit "Book Now" on the same Toyota Corolla for the same weekend, at the exact same millisecond.

The database didn't blink. It said "Yes" to both.

That’s when I learned that

if (isAvailable)

is not a valid way to check inventory in the real world.

The Move to Robust Architecture

I spent the next two weeks tearing down our naive booking logic and rebuilding it with Next.js 15, Supabase, and some serious PostgreSQL locking strategies.

Here is the architecture that finally let me sleep at night:

1. The Database Schema (The Foundation) We stopped storing "Available Dates" and started storing "Ranges". PostgreSQL's

TSTZRANGE

is powerful. instead of checking 100 individual rows for availability, we check for overlaps:

sql

-- The "No Overlap" Constraint

CONSTRAINT no_double_booking EXCLUDE USING gist (

item_id WITH =,

booking_range WITH &&

);

This one constraint does more work than 500 lines of JavaScript. It makes double-booking physically impossible at the database level.

2. Optimistic vs. Pessimistic Locking We moved the availability check inside the transaction. When a user starts checkout:

  • We don't "reserve" the car (locks inventory too long).

  • We check availability efficiently.

  • The Stripe Integration: We use Webhooks to finalize the booking. Only when

    checkout.session.completed

    fires do we insert the final row.

3. Client-Side State (Next.js 15) We handle the real-time aspect using Supabase Realtime under the hood. If someone else is viewing the same car, you see a live "3 people are looking at this" indicator. It’s not just FOMO; it’s an early warning system for race conditions.

The Lessons

Building a booking system isn't about the "Happy Path" where one user books one car. It's about the "Chaos Path":

  • Timezones (Dhaka vs. Chittagong seemed simple until Daylight Savings hit our international clients).

  • Payment failures holding inventory hostage.

  • The "Back Button" problem.

Today, Gaari handles thousands of bookings without a single overlap. Robust engineering isn't flashy, but it’s the only reason our business exists.


I wrote a 3,000-word deep dive on the code, database schema, and transaction logic. It’s open-source knowledge for anyone building a rental platform: https://portfolio-rizwanul.vercel.app/blog/how-to-build-booking-system-nextjs

Join Rizwanul on Peerlist!

Join amazing folks like Rizwanul and thousands of other builders on Peerlist.

peerlist.io/

It’s available... this username is available! 😃

Claim your username before it's too late!

This username is already taken, you’re a little late.😐

0

3

0