The full account of the outbound system: the rules it enforces in code, the shape of the engine, and a capability table that says plainly what works and what does not. We run it on our own pipeline before anyone else's, so this page is written for somebody who wants to check the engineering rather than read a summary of it.
Sending, receiving, authentication and the schedule all run against a real Postgres database with row level security forced on every table. What is still missing is listed, by name, in what is built.
Sized for eight meetings a month at this motion's typical reply rate. Adjust the target in the full model below.
Of warmup before we contact anyone
Messages per mailbox per day, hard ceiling
Sends from kaizensparktech.com, ever
Contacts per company per 30 days
We build software for a living, so we are not renting an outbound tool and hoping. We are building the thing, running it on ourselves, and only then offering it to anyone else.
A system for filling our own calendar: domains and mailboxes we own, sequences we wrote, replies a named person on our team works, and a report we read weekly.
Not a product yet. No client logs in, nothing is sold, no self-serve signup exists. The tiers and pricing page is parked until phase three.
Because the constraint on our pipeline is outbound, and because a system we run ourselves is the only honest basis for later selling it. We carry our own architectural decisions.
These are not guidelines. Each one is code, not a note in a document, because the whole reason DIY outbound fails is that under pressure somebody decides just this once is fine.
kaizensparktech.com is never in the sending path. Cold volume there would put invoices, client replies and password resets at risk. We send from registered near-variants that redirect to the real site.
A mailbox ramps five messages a day toward a ceiling of forty-five. It cannot join a live campaign before its domain is twenty-one days old. The engine refuses; it is not a setting anyone can override in a hurry.
Computed hourly from authentication state, rolling bounce and complaint rates, blocklist status and age. It resumes at 68, not 60 — the gap is deliberate, so a domain sitting on the line does not flap in and out of service.
Hard bounce, complaint, unsubscribe or an explicit ask: the address is out, workspace-wide, with no remove button. A list you can quietly un-suppress is a pause button, and it is the easiest way to end up in front of a regulator.
Three colleagues receiving near-identical mail in one week is how an entire company marks us as spam at once. The throttle is enforced in the send loop.
An unresolved {{company}} is never guessed, never left blank, never silently substituted. The message does not go, and the block is written to the event log so somebody fixes the data.
Pixels are an extra remote image in every message and Apple Mail Privacy Protection made the number meaningless anyway. We report reply rate and seed-measured placement, both of which we can defend.
Drafting is assisted. Sending is not. Nobody on our team sends an unread automated reply to a prospect, because the first time that goes wrong it goes wrong in public.
Five working and one broken produces the same result as none working, which is why they are not separable.
Near-variant domains with MX, SPF inside the lookup limit, 2048-bit DKIM and DMARC. Two to three mailboxes each, because more concentrates the risk. Gmail, Microsoft 365, Zoho or SMTP behind each one.
Peer and seed traffic that is opened, replied to and pulled out of spam. Placement measured weekly per domain per provider. It keeps running alongside live campaigns rather than stopping at go-live.
Multi-step with delays, in-thread follow-ups, spintax, branching on lead attributes, and A/B arms tested with chi-squared rather than a hunch. Stops on reply, bounce or opt-out.
Seed placement testing, blocklist monitoring across four zones, a pre-send content scorer, first-bounce suppression and one-click unsubscribe on every message.
Every reply from every mailbox in one queue, classified before it is answered. Out-of-office pauses the sequence to the stated return date instead of ending it.
The part no software replaces. Somebody on our team reads the reply, handles the objection, and books the meeting with the four BANT fields recorded.
Set the target and the model works backwards to the infrastructure it needs, and forwards to what it would produce.
Positive replies at 32% of all replies and 55% of those converting to a booked meeting — ranges the engine uses, not a promise. Twenty-two working days a month, 45 sends per mailbox per day, and a floor of four mailboxes across two domains so no single domain is a point of failure. Pull the reply rate down to test the pessimistic case.
The engine, the rules and the interface run on a real Postgres database. The worker that speaks SMTP and IMAP is written and tested. What has not happened yet is the first live message to a real person — the sending domain is inside its 21-day warmup, and the system refuses to let it out early.
| Capability | State | Notes |
|---|---|---|
| Sending rules and the scheduler | built | Caps, weekends, the warmup gate, suppression and the company throttle are enforced in Postgres functions, not in the interface |
| Persistence | built | Postgres. Row level security enabled and forced on every table; the key table has RLS forced and no policies at all, so no client can reach it |
| Role enforcement | built | In the database. The interface draws for a role; the database decides. Changing the role in devtools changes what is drawn and nothing else |
| Sending mail | built | A zero-dependency worker speaking SMTP over TLS, with DKIM signing. Tested against throwaway TLS servers; STARTTLS is required and never downgraded. No live message has been sent yet |
| Reading replies | built | IMAP polling with a per-mailbox high-water mark, bounce and out-of-office classification, threads reassembled by Message-ID |
| Domain authentication | built | MX, SPF, DKIM and DMARC resolved from DNS and written back. They used to be checkboxes somebody ticked while the health score docked 64 points from them |
| Blocklist monitoring | built | Real DNSBL queries across four zones. A zone that refuses the query is recorded as unchecked, never folded into “clear” |
| Domain health and auto-pause | built | Recomputed on every write to the row. Pauses below 60, resumes at 68 |
| Sequencing, branching, A/B | built | Chi-squared with Yates correction; reports honestly when a test has not concluded |
| Deliverability lab | built | DNS record generation, blocklist monitor, content scorer, per-record penalties shown as data rather than prose |
| Interface | built | Seventeen views, on the live database. A single HTML file talking to PostgREST |
| Open tracking | built, off | Works, and is off by default. Apple Mail Privacy Protection inflates the number irreducibly, and the interface says so next to it rather than in a footnote |
| Mail accounts | app passwords | Google, Microsoft, Zoho and plain SMTP, authenticated with an app password. The credential is sealed before storage and cannot be read back |
| OAuth | not built | Offered in the form as a disabled option so the gap is visible. The database refuses it outright, so an account that could never connect cannot be created by any route |
| DMARC aggregate reports | not built | The XML that receivers send back is not parsed yet, so authentication is checked by asking DNS rather than by reading what receivers saw |
| Self-serve signup and billing | not built | Deliberately. Nobody outside KaizenSpark logs in during phase two |
The value is not the interface. It is that the sending rules have been written down as running code and tested. When we build the real scheduler, that logic ports directly and the invariant suite becomes the regression suite. See MIGRATION-PLAN.md for the mapping.
Each phase has to earn the next. We do not build multi-tenancy before we have proved the thing works on one tenant, and that tenant is us.
One workspace, our domains, our leads, our team working the inbox. The infrastructure is built and running against a real database; what remains is the domain finishing its warmup and the first live send. Success is meetings on our own calendar and a weekly deliverability report we actually read. If it cannot fill our pipeline, it has no business being sold.
Same system, one workspace per client engagement, operated by us. Clients receive reports and booked meetings; nobody outside KaizenSpark logs in. The multi-tenancy this needs is already in the schema — every row carries a workspace and row level security is forced — so this is an operating decision rather than a rewrite.
Self-serve accounts, billing, a public API, white-label. Only worth doing if phase two shows the operational model holds at more than a handful of clients. The parked go-to-market page is written for this moment and no earlier.
Four decisions cost almost nothing today and are painful to retrofit. Keep them even while there is only one workspace.
Workspace ID on every row from the first migration, even with one workspace. Retrofitting tenancy into a schema that assumes one customer is a rewrite.
Never hardcode the tenant. No WHERE ws = 'kst' anywhere, no implicit current-workspace global in business logic.
Secrets in a real store from day one, not environment files. Phase 3 needs per-tenant encryption keys and you cannot add them to plaintext later.
Stable event schema. Every report we will ever build reads from it. Changing its shape later invalidates every historical number.
Work the reply queue. Classify, answer, book. Interest has a half-life measured in hours, so this is the one thing that cannot slip.
Check alerts. A dead mail token or a paused domain stops sending silently, and the alert is the only thing that tells you.
Read the deliverability report. Seed placement per provider, bounce and complaint trend, anything paused and why.
Review sequences against reply data, tighten the ICP, retire losing A/B arms once a test has actually concluded.
| Role | Owns | Cannot |
|---|---|---|
| Owner | Everything, including roles and workspace settings | — |
| Admin | Campaigns, domains, mailboxes, leads, imports, alert rules | Change roles |
| SDR | The reply inbox, replies, meetings, suppressing a lead | Touch domains, mailboxes or connections |
| Analyst | Reading everything | Send, edit or suppress anything |
Enforced in the interface today and only in the interface. Until the server enforces it, treat the role separation as a working agreement between us rather than a control.
Four documents and two pages. Start with the platform, then the migration plan when you are ready to build the real thing.