NotesOctober 8, 2026

Two people, one slot: stopping double bookings

Every booking form has the same hidden trap. The server checks that a slot is free, then saves the booking. Those are two steps, and two visitors can arrive between them. Both pass the check. Both get a confirmation. One of them turns up to a studio that is already busy.

We built Northlight booking, a concept booking site for an imaginary photo studio, to solve this one thing properly.

The fix is one transaction

The check and the save run inside a single write transaction. In SQLite, BEGIN IMMEDIATE takes the write lock before the check runs, so a second request waits until the first one has either saved its booking or given up. When it is the second request’s turn, the first booking is already there, and the answer is a clear “taken”.

db.exec('BEGIN IMMEDIATE');
const clash = busyStmt.all(date).some((b) => overlaps(start, end, b.start, b.end));
if (clash) {
  db.exec('ROLLBACK');
  return null;
}
insertStmt.run(reference, token, service, date, start, end, name, email, note);
db.exec('COMMIT');

Overlap matters as much as equality. A 90 minute session that starts at 11:00 blocks a 12:00 start, even though the two start times are different. The check compares ranges, not labels.

Proving it with a race

A fix like this is easy to believe and hard to see, so we wrote a test that does what real visitors do on a busy day. Five requests ask for the same slot at the same moment. The test passes only if exactly one booking wins and the other four are told the slot is taken. It does, every run.

What the visitor sees

The losing visitor does not get an error page. The time frame they picked is struck through, the summary says it was just taken, and the next free time is one tap away. A race the visitor loses should still feel like the site is on their side.

The short version

If two steps must never be split, make them one step on the server and test the split on purpose. A browser cannot protect a slot. Only the place where the booking is saved can.

Tell us what you want to build.

Every project is scoped from your tasks and priced after we read your brief.

Start a project
  1. 01Send the brief A few fields. Ten minutes is enough.
  2. 02Get a written quote Scope, price and a delivery date.
  3. 03Watch it get built A private preview link while we work.