TechnicalProduct
A campaign as a state machine, not a send list
- Organisation
- tmrwX · Family Hub campaign engine
- Role
- Product architecture, workflow design and delivery
- Period
- 2026 · Malaysia
Rebuilding a flat sequential campaign builder into an event-driven engine that pauses the moment a real person replies, and hands the relationship to an adviser with a timer on it.
At a glance
- Situation
- The campaign engine was a flat sequential builder. An operator picked an audience and queued the sends, but the engine kept sending after real customers replied mid-sequence.
- Stakes
- Duplicate and tone-deaf messages under live customers cost trust directly, and warm leads went cold because no adviser knew the moment a lead became theirs.
- My role
- Product architecture, workflow design and delivery of the migration to an event-driven state machine.
- Constraints
- Live campaigns running through the migration, historical reporting that could not be lost, and a shared WhatsApp business sender.
- What changed
- Duplicate dispatches stopped after the migration
- Any customer journey is reconstructable from the append-only event ledger
- Advisers receive real-time handoffs with an SLA timer instead of discovering leads late
- Read this if
- Your marketing automation misbehaves the moment customers act like humans instead of a send list.
- dispatched after the migration
- No duplicatesdispatched after the migration
- reconstructable from the event ledger
- Full journeyreconstructable from the event ledger
- handoffs on the adviser dashboard
- SLA-timedhandoffs on the adviser dashboard
How the system actually worked

Scroll the figure sideways to read it, or turn your phone.
Nine steps, from enrolment to a confirmed visit.
Scroll the figure sideways to read it, or turn your phone.
- Every transition runs through one deterministic handler with worker-aware locking. Two workers evaluating the same enrolment cannot both dispatch.
- The ledger is append-only. Enrolled, sent, opened, clicked, replied, booked, attended, opted out. The whole journey is reconstructable from it.
- A human signal pauses automation instantly. Someone who replies does not receive tomorrow's scheduled nudge.
- Handoff starts a clock. The adviser dashboard shows the timer, so a warm lead going cold is visible rather than discovered late.







Stack & practices
- Express
- TypeScript
- PostgreSQL
- Socket.IO
- Infobip
- Twilio
- React