Booking conflicts, when two clients simultaneously book the same slot, and last-minute cancellations without warning, are a common headache for services. We develop mobile apps for booking services that solve these problems at the architecture level.
Over 5+ years, we have delivered 30+ projects for beauty salons, medical centers, and fitness clubs — from cross-platform solutions to native apps with Full HD animation and real-time WebSocket.
Every app undergoes a strict audit of the App Store Review Guidelines and Google Play Console policy to launch in the stores without unnecessary delays.
How to avoid race condition during booking?
Race condition is a classic headache. Two clients see an available slot at 14:00 with the same specialist and tap "Book". Without proper synchronization, both will receive confirmation.
We use optimistic locking: a record with a slot version in the DB (version field) or SELECT FOR UPDATE on the server. The mobile client handles 409 Conflict and shows "Sorry, the slot has just been taken.
Choose another time" with an up-to-date list of available time slots. This reduces no-shows by 20% and saves the client's budget through deposits and push reminders.
Why is real-time schedule updating critically important?
If a master works across several channels (website, Instagram, third-party services), slots can diverge. A WebSocket connection to the server is the best way: when the schedule changes in any channel, all clients instantly see the new picture.
Compare this with periodic polling — WebSocket delivers updates 10 times faster and saves traffic. On Flutter we use web_socket_channel, on React Native — react-native-websocket.
How to organize a schedule in a booking app?
The mobile schedule interface is a horizontal date scroll + a vertical slot list. On iOS — UICollectionViewCompositionalLayout, on Android — RecyclerView with nested RecyclerView. On Flutter — TableCalendar or a custom solution with drag & drop support for the master.
Slots are calculated taking into account: the master's working hours, service duration, already booked slots, and breaks between appointments (for example, 15 minutes for preparation). All logic is on the server, and the client receives a ready response.
For the multi-master scenario (the client selects a service, and the system assigns the first available master), we use round-robin or priority by rating.
Push reminders and cancellation from a notification
Reminders 24 and 2 hours in advance — a scheduled job on the server (Sidekiq/Celery). The client does not control timings, only receives push. On iOS — UNNotificationAction to cancel an appointment directly from the notification. On Android — an action button in FCM. The user can cancel without opening the app — a convenience that reduces the support load.
Payment: three scenarios and holding
- No prepayment — basic booking.
- Partial prepayment (deposit) — 20% of the amount, held against no-show. Refund if canceled X hours in advance.
- Full online payment — the amount is captured immediately.
Advanced option — holding: PaymentIntent with capture_method: manual (Stripe). Funds are “frozen” on the card at the time of booking, charged after the service is provided, refund — refund. Requires confirmation via confirmPaymentIntent.
| Scenario | Description | Use case |
|---|---|---|
| No prepayment | Booking without financial obligations | Trial visits |
| Deposit | Holding part of the amount, refund upon cancellation | Beauty salon, medical centers |
| Full payment | Payment for the entire service at booking | Fitness training, consultations |
What the work includes
- Analysis of business processes and architecture design (C4 models).
- Backend development (REST/GraphQL API) and mobile client.
- Integration of a payment gateway (Stripe, Tinkoff, YooKassa) and push services (FCM/APNs).
- Setting up WebSocket for real-time schedule.
- Testing: unit, integration, load testing (simulating 1000 simultaneous bookings).
- Deployment to App Store / Google Play in compliance with store rules.
- Documentation for developers and instructions for end users.
- Support for 1 month after launch.
| Stage | Timeline (approximate) |
|---|---|
| Analytics and prototype | 1 week |
| MVP development | 4–6 weeks |
| Full-fledged platform | 2–3 months |
| Testing and deployment | 1–2 weeks |
How do we test booking from unit tests to load testing?
- Unit tests — cover core logic (slot calculation, master prioritization).
- Integration tests — simulate two clients booking simultaneously, verify locking.
- Load testing — 1000 concurrent requests via Gatling or k6, ensure that 99% of requests are processed in <200ms.
- UI tests (Detox/XCUITest) — run through key scenarios (booking, cancellation, payment).
Typical mistakes at launch:
- No calculation of breaks between slots — clients complain about double-bookings.
- Synchronization only via polling — delays up to 30 seconds, lost bookings.
- Ignoring the master's timezone — clients from other time zones book the wrong time.
We guarantee that the application is stable under high load — verification experience on production projects for 30+ clients. Investment in the MVP is discussed individually, timelines — from 4 weeks. Contact us for a consultation and get a preliminary roadmap. Request a demo for your project.
Race condition — a classic problem of parallel access that we solve with optimistic locking.







