← all case studies · Sebenza · Workflow Engine · PR #398 + #400

The Welcome Email Gauntlet

Adding a client used to email them instantly — and thanks to a race in the queue, sometimes twice. Now four gates stand between a click and a customer's inbox, and the queue can't run the same job twice. Both simulations below are live — flip the switches and watch what reaches the inbox.

1 · From click to inbox

Every path writes an audit row — that's the paper trail, and nothing suppresses it. The email only continues if it clears both gates. CSV import never even asks, so a bulk import of your existing customers can't mail anyone.

0
audit rows written (always)
0
emails prevented
0
emails delivered

2 · Why one client got two emails

The queue has two independent workers draining it — an Inngest job and the billing cron. The old code read a pending job with a plain SELECT, sent the email, and only marked the job done afterwards. When both workers woke at the same moment, both read the same job. Run the race in both modes.

-- before: no claim between reading the job and running it SELECT * FROM workflow_queue WHERE status = 'pending' LIMIT 50; -- ...send the email... then mark completed. Two workers = two sends.

3 · The four gates, in plain terms

All four must agree before a welcome email leaves the building. Any one of them says no → the client is still saved, the audit row is still written, and nobody gets mail.

GATE 1

The org switched it on

The client-welcome workflow is now off by default for every business. It stays free — it just isn't automatic. A business that wants it flips it on once, in Settings.

GATE 2

The request asked for it

The API only fires the workflow when the request carries sendWelcomeEmail: true. Its default is false — filing a client is not consent to email them.

GATE 3

A human ticked the box

The Add Client dialog always had a “Send welcome email” checkbox — it was decorative: the page dropped it from the payload. It's wired now, and starts unticked.

GATE 4

CSV import never asks

Bulk import uses the same endpoint but sets no flag at all, so importing your existing book can never blast “thanks for choosing us” at 200 people who chose you years ago.

Is the email useful? Yes — in exactly one situation. A genuinely new client, added the day you start working together: it sets expectations before your first invoice lands, and a first opened email teaches their mail provider that your invoices aren't spam. It's wrong for backfills, imports, and record-keeping — and the system can't tell those apart, so the human adding the client says.

4 · The receipts

Both behaviours were proven with real sends against production, not by reading code.

Resend delivery log · one client created each time
Aug 27 · 00:20:05[delivered]Welcome email — before the fix
Aug 27 · 00:20:06[delivered]the duplicate, 1 second later
— queue claim shipped (#398) —
Aug 28 · 00:10:01[delivered]exactly one, held for 2 min of polling
Sebenza · workflow queue + client-welcome opt-in · PRs #398 (atomic claim) & #400 (four gates)