QueueLite
Live in productionQueue management for small clinics
Frontend
React 19 · Vite
Backend
Express 5 · Node 20
Data
PostgreSQL · Supabase
Hosting
Vercel · Render
01The problem
Small clinics run their queue on a paper register and a raised voice. Nobody knows how long they'll wait, so nobody leaves the room.
What's actually scarce: the doctor's time, or knowing where you stand?
02The solution
Show everyone where they stand: a desk for staff to issue tokens, a board for the waiting room, and a tracker on each patient's phone.
Live at Dev Eye Care, Moradabad, handling 30–40 patients a day.
03Architecture
React on Vercel, an Express API on Render, Postgres on Supabase. Vercel proxies /api to Render, so it runs as one origin: no CORS, first-party cookies.
One origin, three surfaces on three different clocks, and a snapshot cache so a full waiting room costs one database read. Connections: Staff desk to Vercel (10s); Waiting board to Vercel (10s); Patient tracker to Vercel (10s → 2m40); Vercel to Express 5 API (same origin); Express 5 API to Snapshot (serve); Snapshot to PostgreSQL (1 read); Express 5 API to PostgreSQL (writes · invalidate).
scroll the diagram sideways →
04Technical depth
- A unique index on (clinic_id, token_day, token_number) makes duplicate tokens impossible; a clash just retries.
- The bug that actually bit was IST midnight, not a race. Fixed by storing the day instead of deriving it.
- Polling, not WebSockets: every 10s near the front of the queue, stretching to 2m40 at the back.
- A 2.5s snapshot means a whole waiting room refreshing at once costs one database read.
A rule in application code is one you have to remember. A rule in the database remembers itself.