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.
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.
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.
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.
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.
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.
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.
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.
Both behaviours were proven with real sends against production, not by reading code.