A No-Show Escalation Engine on Laravel 13 and Reverb
Horizon, Reverb, case-study, Laravel, architecture, scheduling, real-time, PostgreSQL
A No-Show Escalation Engine on Laravel 13 and Reverb

A No-Show Escalation Engine on Laravel 13 and Reverb

**One idempotent hourly job replaced every manual check for a missed intervention, and by construction it cannot escalate the same student twice no matter how many times it runs.** ## Outcome One idempotent hourly job replaced every manual check for a missed intervention, and by construction it cannot escalate the same student twice no matter how many times it runs. ## Context This was contract work for a K–12 education platform built on Laravel 13, Horizon, Reverb, and PostgreSQL. I worked with the client team on the scheduling path staff use to manage student support-room interventions; my scope was the no-show detection, escalation, and live-alerting path. ## Problem Schools assign students to support-room interventions with a due date. When a student does not show, staff have to notice the miss and escalate to the next consequence tier. Tracked by hand across a whole school, misses slip through and escalations land inconsistently. The platform needed a deadline-driven engine that detects overdue sessions on its own, advances each one through a fixed ladder of consequences, and tells the people watching the board the moment something changes. This is the no-show escalation engine, a self-contained body of detection, escalation, and alerting on Laravel 13 with Horizon and Reverb. ## Constraints - "Overdue" is defined in each school's local day, not server UTC, so the boundary is timezone and DST sensitive. - Due dates move: sessions get rescheduled or excused, so any decision computed in advance can be wrong by the time it would fire. - Double-escalating one missed session is a real-world harm, not just a data glitch, so the engine has to be idempotent under retries and races. - Staff watch live boards that must reflect a new no-show without a manual refresh. - Contract work under NDA, so figures here are relative. ## Decisions and trade-offs **Rejected: a delayed job dispatched at session-creation time**, scheduled to fire at the due date. It reads clean until a due date changes. Rescheduled and excused sessions leave queued jobs that must be found and cancelled, and a job queued days out drifts against a school's local clock across a DST change. The queue becomes a second source of truth to reconcile. **Rejected: a scheduled broadcast that only nudges staff to act.** It pushes the judgment back onto humans and never creates the escalation record itself, which is the whole point. **Chosen: an hourly poll that reads current state each run.** `MarkOverdueSupportRoomSessions` runs hourly, `withoutOverlapping` and `onOneServer`, and transitions sessions still scheduled past their due date into no-show using the school's local day. Because it re-reads state every hour, a session rescheduled between runs simply no longer matches. There is no stale job to cancel. Escalation is a separate action, and idempotency lives there. It takes a row-level `lockForUpdate`, guards that the session is still in the no-show state, advances exactly one rung of the ladder, lunch to after-school to Saturday to in-school to out-of-school to restorative, and throws a dedicated exception when the ladder is exhausted. The lock plus the status guard mean a repeated poll, a retried queue job, or a double click all collapse to a single escalation. There is no backoff to tune because there is nothing unsafe to retry. Every state change then emits a broadcast over Reverb so open boards update in place. ## Implementation I implemented `MarkOverdueSupportRoomSessions` as an hourly, non-overlapping, single-server job within the client team's scheduling platform. The escalation action uses a row lock and status guard before advancing one tier, then broadcasts each committed change through Reverb for live boards. ## Results Detection is timezone-correct and self-correcting: it always acts on the current schedule, so reschedules and excuses need no cleanup. Escalation is idempotent by construction rather than by convention, which removes the class of bug where a student gets punished twice for one miss. Staff see no-shows and escalations appear live. The manual tracking of missed interventions dropped to zero, and the engine's behavior is now a walkable design with each trade-off written down: poll over delayed job, locked ladder over hopeful retries, broadcast over inbox. ## Takeaways When the scheduled fact can change, derive it from current state rather than trusting work queued far in advance. For consequences with real-world impact, make retries safe at the state transition itself.