A company run by 20+ workflows, with a gate in front of every email
Five entry points, one owner per contact, a database-side send gate that refuses unsafe mail, and observability that notices when a job stops.
The problem
DreamFoxVerse is run by one person. Every lead, reply, payment and client brief has to be handled within minutes, at any hour, without a team, and without the automation ever mailing the wrong person or quietly breaking.
The system
- Five entry points (free-audit form, contact form, inbound email, payment webhook and a paid client portal) classify the person and write to one customer record in Postgres.
- One engine owns each contact at a time: nurture, outbound, support or client messages. Ownership is recorded, so two engines cannot work the same person.
- Every send passes a send gate implemented as a Postgres function: opt-out, bounce suppression, ownership, cooldown and a daily cap, and marketing is refused for anyone on an active paid plan.
- A central error handler records every failure. A watchdog checks every 30 minutes that each scheduled workflow actually ran, and the daily digest only reports all green when it has seen the whole window.
Key decisions
Fail closed at the gate
WhyIf the database cannot be reached, the email is not sent and an alert is raised.
Trade-offA legitimate email can be delayed; mailing someone who opted out cannot be undone.
Assert side effects, not green runs
WhyWorkflow nodes set to continue on error look successful while failing. Checks read the written row, the delivered email and the HTTP status instead.
Trade-offSlower tests that touch real systems, and they found failures a green dashboard had hidden for weeks.
Liveness from the schedule’s longest legitimate gap
WhyA weekday job legitimately pauses for 72 hours over a weekend; alerting on its average cadence cried wolf every Saturday.
Trade-offSlightly later detection for weekday-only jobs.
Put guards in the database, not in each workflow
WhyA drip that is already waiting resumes with its old workflow snapshot. A Postgres function or trigger applies to every writer immediately.
Trade-offLogic in SQL needs its own migrations, rolled-back dry runs and revert scripts.
Results
- 20+ production workflows share one send gate and one error handler
- 25+ live end-to-end checks that read real side effects
- Each guard proven by reverting its fix and watching the test fail
What I’d do next
Move the workflow logic that matters most into versioned, unit-tested code, and replace execution-log polling with a single run-log table.