Scenario · Custom web app · Medical practice

A front desk that stops
living on the phone.

Several specialists’ schedules managed by hand and whole mornings on the phone. Simple online booking for patients, automatic reminders to reduce missed appointments and health data kept safe.

Project typeCustom web app
SectorMedical practice
Typical timing9–12 weeks
●Scenario
web app · bookings
Medical Practice
ONLINE SCHEDULE
Online
Cardiology
Dermatology
Orthopedics
Neurology
MON
TUE
WED
THU
FRI
●
Booked
Free
Urgent
WED 12 JUN · 09:30
P
Patient
Patient since 2022 · urgent ECG
Urgent
30 min
Automatic reminders
SMS −24h ✓ Sent
Email −48h ✓ Sent
SMS −2h ○ Pending
MANAGE APPOINTMENT

Web app scenario — bookings for a medical practice

An Excel sheet as
a booking system

The scenario: a medical practice with four specialists, dozens of appointments a week and a front desk that spends much of the day on the phone. The diary is entirely manual: a central front desk, an Excel sheet shared on Google Drive and handwritten reminders.

The problems are obvious: patients can't find a slot outside office hours, there are many no-shows because nobody reminds people, and reports are still handed over in person or sent in scattered emails. The practice needs a system that keeps working when the front desk is closed.

A typical constraint: the system has to connect to the medical software already in use via API, without replacing it — the practice doesn't want to change an internal tool that already works.

Client Private medical practice, 4 specialists (example)
Industry Private healthcare · Outpatient clinic
Year Typical duration · 9–10 weeks
Main stack
React 18 Node.js 20 PostgreSQL Twilio SMS Redis Stripe
Role Full-stack developer · UX design

24/7 self-service booking

Patients must be able to book on their own, choosing specialist, date and time — even at 11 PM. No phone call needed for standard slots.

Automatic SMS + email reminders

Notifications at −48 hours (email) and −24 and −2 hours (SMS) with a link to confirm or cancel. Every cancellation frees the slot in real time and sends the patient a confirmation.

Patient portal and digital reports

A private area for each patient: visit history, the option to download reports as PDF, upcoming appointments and personal data management (GDPR compliant).

Integration with the existing medical software

Two-way sync with the internal software: new bookings go into it, and changes made by the doctor show up on the portal in real time.

Selective advance payment

Some visits require a deposit at booking time (via Stripe) to reduce no-shows. Reception must be able to enable this option per visit type.

Online booking portal requirements

Four schedules, zero conflicts,
a system that runs by itself

Healthcare has precise constraints: health-data privacy (GDPR), concurrency on slots, reminders that — if they don't arrive — cost the practice real money. Every part of the system has to be robust by design, not "best effort".

01

Race conditions on slots

Two patients booking the same slot at the same instant can both get a confirmation. Without a lock, collisions happen — especially at peak times, right after reminders go out.

02

100% reliable reminders

An SMS not delivered at −24 hours is a lost visit and an empty slot. Sending latency varies, and a Node.js server can't keep timers in memory: if it restarts, reminders are lost.

03

Sync with the medical software

The internal software's API is often REST but poorly documented and without webhooks. Doctors' changes (reschedules, urgent cancellations) need to reach the portal almost in real time without a notification from the software.

04

Health data and GDPR Art. 9

Medical data falls under the GDPR's "special categories": explicit consent, right to erasure, access logs. The system had to be privacy-by-design, not an afterthought.

05

Accessible UX with zero learning curve

Patients include older people who aren't used to digital tools. Booking has to take under 90 seconds, with no account required on first visit and WCAG 2.1 AA accessibility.

Technical challenges of a digital medical schedule

Optimistic locking, a job queue
and a portal that works through the night

01 / 03

Atomic booking with optimistic locking on PostgreSQL

To eliminate double bookings it uses optimistic locking: each slot has a version column that increases with every change. A booking updates the slot only if the version matches the one read — if someone booked in the meantime, the transaction fails and a guided retry follows. No deadlocks and good performance under load.

On the server it's a single PostgreSQL transaction: read the slot, check it's free, update with WHERE version = $expected; if no row is updated, return SlotConflictError and the client shows a message with the nearest free slots.

// Node.js · PostgreSQL · optimistic lock on schedule slot async function bookSlot(slotId, patientId, paymentIntentId) { const client = await pool.connect(); try { await client.query('BEGIN'); // read the slot with a row lock const { rows } = await client.query( `SELECT id, version, status FROM slots WHERE id = $1 AND status = 'available' FOR UPDATE SKIP LOCKED`, [slotId] ); if (rows.length === 0) { await client.query('ROLLBACK'); throw new SlotConflictError('Slot no longer available'); } // atomic booking await client.query( `UPDATE slots SET status='booked', patient_id=$1, payment_intent=$2, version=version+1 WHERE id=$3`, [patientId, paymentIntentId, slotId] ); // queue the reminders in the job queue await scheduleReminders(client, slotId, patientId); await client.query('COMMIT'); } catch (err) { await client.query('ROLLBACK'); throw err; } finally { client.release(); } }

02 / 03

A persistent job queue for reliable reminders

Reminders don't use setTimeout but persistent jobs on BullMQ + Redis. Each booking adds 3 jobs with the right delay: −48 hours email, −24 hours SMS, −2 hours SMS. If the server restarts, the jobs stay in Redis and run at the right time. The SMS service (e.g. Twilio) only receives the request when it's time to send, with automatic retry if the network fails.

Cancellation by SMS (the patient replies "CANCEL" to the SMS) triggers a Twilio webhook that removes the confirmation job, frees the slot in PostgreSQL and sends an email notification to the practice — all without human intervention.

BullMQ Dashboard · Reminder Queue
REMINDER QUEUE
● 3 active example queue
reminder:sms:−24h
Patient A · slot 12/06 09:30
in 22h 14m
delayed
reminder:email:−48h
Patient B · slot 13/06 11:00
in 46h 02m
delayed
reminder:sms:−2h
Patient C · slot 11/06 14:00
completed 09:47
completed

03 / 03

Patient portal and sync with the medical software

The patient portal is a React app with sign-in via an email link: no password to remember, nothing in the way on first visit. Each patient sees past visits, downloads PDF reports uploaded by the doctor and manages active bookings.

If the software has no webhooks, sync happens through a process that queries it every 60 seconds and compares schedules with the internal state. Changes found (reschedules, cancellations, new availability) are applied to the database and reach the React clients via Server-Sent Events — real-time updates without WebSockets, simpler to run behind a reverse proxy.

Development process for a booking app

9–10 weeks, three actors,
one system that runs itself

There are three people in the project: the head physician (decides and knows the domain), the front desk (uses the diary every day) and patients (use the portal). Observation sessions at the front desk come before any code: understanding the real flow is more useful than any requirements document.

Weeks 1–2

Discovery and domain analysis

Observing the front desk's work, mapping visit types and diary constraints per specialist, analysing the medical software's API. Data structure and GDPR requirements.

Output: DB schema, portal wireframe, GDPR plan

Weeks 3–4

Core backend: slots, locks and job queue

Diary model on PostgreSQL, locking with FOR UPDATE SKIP LOCKED, BullMQ + Redis, first SMS reminder sending. Load tests with dozens of simultaneous bookings.

Output: stable REST API, no double bookings in tests

Weeks 5–6

Patient portal and schedule frontend

React SPA with magic link auth, a 3-step booking flow (specialist → slot → confirmation), private area with visit history and report downloads. Focus on WCAG 2.1 AA accessibility and usability for non-technical users.

Output: portal tested with a few real patients

Weeks 7–8

Medical software integration + Stripe + reminders

A sync process with the medical software that detects differences, two-way updates, Server-Sent Events for the front end. Stripe for deposits on some visits. Full testing of SMS cancellation.

Output: reminder pipeline tested with hundreds of simulated jobs

Weeks 9–10

UAT, GDPR audit and progressive go-live

Sessions with the front desk and head physician, UX tweaks on urgent cases, GDPR review with the practice's legal adviser. Go-live in 3 phases: one specialist → a second → everyone. Active monitoring for the first 72 hours.

Goal: no critical issues in the first week

Solution: optimistic locking and SMS reminders

React + Node.js at the core.
Every choice justified.

React + TypeScript
Node.js + Express
PostgreSQL
Redis + BullMQ
Twilio SMS
Stripe Payments
Nodemailer + SES
AWS S3 (PDF reports)
Vite
Jest + Supertest
Zod (validation)
date-fns (time handling)

Why a magic link and not a password?

Patients include older people or people not used to digital tools. A password means "I forgot my password" as the first contact with the portal. An email link — single-use, valid 15 minutes — removes the problem: if you have your email, you have the portal. First-time patients don't even need to register: details are collected during booking.

Why SSE and not WebSockets?

WebSockets need dedicated infrastructure (sticky sessions, proxy support) that complicates deployment on shared hosting. Server-Sent Events work over normal HTTP, are supported by all modern browsers and cover the real use case: one-way updates from server to client (slot freed, appointment moved). Less infrastructure, same result.

Example goals — medical bookings

More online bookings.
The front desk stops being a bottleneck.

Example figures, not a client's results: realistic goals for a scenario like this, to be measured in the months after launch against the same period before.

×4
Online bookings
goal as a share of the total
−50%
No-show rate
goal with automatic reminders
−60%
Calls to reception
only urgent and complex cases
25%+
Out-of-hours bookings
after 6 p.m. or at weekends
4,5/5
Patient satisfaction
goal in the post-visit survey
0
Double bookings
goal with optimistic locking

«We used to spend half the morning on the phone taking bookings. Now we only deal with things that really need our attention.» That's the result to aim for: a front desk doing the work it's qualified for.

— The project's concrete goal

Goals: more online bookings

What I bring
to every project like this.

→

Observing before designing counts double in healthcare. Front-desk sessions almost always reveal a real flow that differs from the written requirements. How a doctor "moves" slots, for example, is rarely documented — and can break a digital diary if you don't see it in person.

→

Reminders are tested by simulating time, not waiting for it. With time mocking in tests, the clock jumps 24 hours in a few milliseconds and you check the job fires. Faster tests, higher coverage.

→

Email-link sign-in removes almost all first-visit support requests. No "how do I register" or "I lost my password". For people with little digital experience, lowering the barrier matters more than any advanced feature.

→

Healthcare GDPR has to be designed into the architecture, not bolted on. Access logs for reports, explicit consent, retention periods and the right to erasure built into the database structure cost a couple of days at the start. Adding them later means rewriting part of the system.

→

A gradual rollout by specialist protects the system's reputation. Starting with one specialist surfaces the diary's edge cases (follow-up visits of variable length, slots blocked for internal meetings) before they hit every patient in the critical first hours.

Do you have a process that still runs on phone calls and Excel?

Schedules, bookings, automatic reminders — if the flow already exists, it can be digitized without turning everything upside down.

Have a similar project in mind?

Tell me about it: we start from goals and priorities, and the first call is free.