A reservation system I built that handles concurrency (so people can't double-book slots).
It's a full-stack app where service providers (like salons or restaurants) can list their services, and customers can book appointments. The cool part is the backend logic that prevents race conditions. If two people try to book the last slot at the exact same millisecond, the system uses Redis locks to make sure only one succeeds.
- Frontend: react (vite), tailwind CSS (for styling)
- Backend: node.js, express
- Database: postgresql (stores data), redis (handles locks)
- install dependencies:
npm install(root) andcd client && npm install. - create DB:
createdb bookd. - seed data:
npm run seed. - start backend:
npm start. - start frontend:
cd client && npm run dev.
check out the docs/ folder for more detailed (but simple) info:
- customer:
[email protected]/password123 - provider:
[email protected]/password123
I made a script to prove it works!
run: node utils/test-race-condition.js
it tries to book the same slot with two users at once. one will fail.
here, the redis MONITOR shows only the success full requests. the failed requests are not shown.
User A tries to grab the lock for seat/slot ID b0fab6a0…
User B tries to grab the lock for seat/slot ID b0fab6a0…PX 10000 = expire in 10 seconds
NX = only set if not exists
"exists" "lock:slot:b0fab6a0-bf28-4cbb-b096-adaa9f122a2c" user A double-checks: “Is the lock still mine?” → Yes (returns 1)
"GET" "lock:slot:b0fab6a0-bf28-4cbb-b096-adaa9f122a2c" user A reads who owns the lock → sees their own random token
"DEL" "lock:slot:b0fab6a0-bf28-4cbb-b096-adaa9f122a2c" user A finished booking → cleanly releases the lock, releasing the lock immediately will prevent deadlock !!!
here's the test script logs:
if any problems or the way of testing itself feels off, please raise an issue.

