safesend

a campaign engine you can stopinteractive demo · synthetic contacts · nothing is ever sent

Anyone can write a loop that sends messages. The engineering is in everything that refuses to send one.

This is a broadcast engine with the safety rails made visible: opt-in enforced, opt-outs permanently suppressed, contacts deduplicated across runs, a hard daily cap, one message per second, dry run on by default — and a kill switch you can pull mid-flight that still leaves the state resumable.

1 · The audience, before anything is sent

60 contacts · 12 already sent today · 2 opted out
39Will be messaged
21Excluded, with a reason
188Capacity left under the cap
Replied STOP2

Replied STOP — permanently suppressed

No opt-in on record6

No recorded opt-in; template send would breach policy

Malformed number4

Malformed number: +9112345

Already messaged9

Messaged on a previous run — deduplicated

Daily cap reached0

2 · Run it

Dry run — nothing is emitted

Plan it first to see who gets filtered out and why. Then turn off dry run, start the send, and pull the emergency stop while it is mid-flight.

The business story

Why this system exists

I ran a production broadcast engine on a company's real inbound WhatsApp number. That single detail sets the entire design: the number that receives customer enquiries is the same number the campaign sends from, so a bug does not cost you a campaign — it costs you the channel. WhatsApp enforces its Business Messaging Policy with quality-rating downgrades and number bans, and a banned number takes every legitimate conversation down with it.

What I actually built and ran

A scheduled broadcaster with a rate limit of one message per second, a hard bulk cap per day, state restored between runs so a contact is never messaged twice, opt-out suppression, a dry-run switch, and a separate emergency-stop workflow that required typing STOP to confirm — it cancelled in-flight runs and disabled the scheduler outright. Safety was not a feature added later; it was the reason the thing was allowed to exist on that number at all.

The judgment calls

What went wrong, and what I'd change

The rail I would add next is a pre-send diff: show the operator exactly which contacts changed cohort since the last run before anything goes out, because the failure I worry about most is not a crash — it is a silently widened audience that nobody reviewed. I would also track quality-rating movement against send volume over time, so the ceiling is discovered from data rather than from a suspension notice.