Skip to content
Mehedi Hasan Sarkar
All case studies

Stopping double bookings on a court booking platform

Sports booking · AustraliaIndependent Contractor, 2026 to present

Problem

On a multi-sport court booking platform in Australia, two players could book the same court at the same moment. This is the hardest problem in a booking platform. If both requests pass the availability check before either one is saved, the venue gets a double booking. Then one player arrives at the venue and cannot play.

There was a second problem, and it was harder to notice. A player can start checkout and then leave before finishing. That player still holds the slot. Unless something releases it, the court looks busy when it is actually free.

Solution

I made the server the only place that decides availability and price. So the app can never send an old price or an edited price.

When a player starts a booking, the server creates a temporary booking, called a hold. The hold expires automatically through a MongoDB TTL index. A TTL (time to live) index tells MongoDB to delete a record automatically after a set time. So abandoned holds disappear without a separate cleanup job.

To stop double bookings, each booking writes a court-day guard document inside a MongoDB transaction. The guard is a record for that court on that day. A transaction groups several database writes, so they all save together or none of them save. Two overlapping requests cannot both commit (save their changes). One succeeds, and the other is rejected.

Player APlayer BHold, expires in 10 minHold, expires in 10 minTRANSACTIONCourt-day guardone commit per slotBooking confirmedRejected: slot taken
Both players reach the guard at the same time. Only one transaction can commit.

The trade-off. Once a hold is saved, nobody else can take that slot. If a player opens checkout and then leaves, the court looks busy for up to 10 minutes. I accepted that. Without a hold, two players can both reach payment for the same slot. Then one of them gets a refund instead of a court. The hold restarts when payment begins. So a player who is really paying never loses the slot in the middle of payment.

Impact

  • Two overlapping requests can no longer both succeed. The transaction lets only one of them commit.
  • Abandoned checkouts release their court automatically.
  • The price a player sees and pays always comes from the server.

Related case studies

Have a similar problem?

Tell me what is breaking or what you need built. I will reply with how I would approach it.

Let's talk