Why your transactional email needs a queue, not a try/catch
Almost every codebase I've inherited sends email the same way: somewhere inside a POST handler, between the database write and the response, there's an await on the mail provider's SDK. It works, for months. Then one afternoon your signup endpoint starts timing out, and it takes an hour to work out that the cause is your email provider having a bad day three thousand kilometres away. I build Pulsenote , a transactional email API, so I've spent an unreasonable amount of time in the space between "your API call returned 200" and "the message is in the inbox". This post is what lives in that gap, why a try/catch doesn't cover it, and where the line sits between "you need a pipeline" and "you're overengineering a side project". The naive version Here's the code. You've written this. // users.controller.ts @ Post ( ' signup ' ) async signup (@ Body () dto : SignupDto ) { const user = await this . users . create ( dto ); await this . mailer . send ({ to : user . email , subject : ' Confirm your email ' , html : renderConfirmation ( user ), }); return { id : user . id }; } Nine lines, obvious intent, no infrastructure. For a lot of applications this is genuinely the right answer, and I'll come back to that at the end. But let's be precise about what it costs, because "it's fine" and "I haven't measured it" are different statements. It puts a third party in your request path. Your p99 for POST /signup is now your p99 plus the provider's p99. Not their median — their tail. A slow provider becomes a slow endpoint, then no endpoint. This is the failure mode that actually takes services down. If the provider degrades to five seconds per call, every signup request holds a connection and an event-loop continuation for five seconds. Your connection pool fills, your load balancer queues, health checks fail, the pod gets restarted, and now you're down — because of email. The blast radius of a non-critical dependency became the whole endpoint. A provider 5xx loses the mail entirely.