Sending Email Is Easy. Sending It Well Is Not.
Calling an email API is one line of code. Making it reliable in production takes more thought. Here are the patterns that matter.
1. Never Send Synchronously
Do not call the email API in your request handler. If the API is slow or down, your entire endpoint blocks.
// Bad: blocks the request
app.post('/signup', async (req, res) => {
await smtp.emails.send({ ... }); // If this takes 5s, user waits 5s
res.json({ success: true });
});
// Good: queue it
app.post('/signup', async (req, res) => {
await queue.add('send-welcome-email', { userId: user.id });
res.json({ success: true }); // Returns immediately
});
2. Handle Errors Gracefully
Email API calls can fail. Network issues, rate limits, invalid addresses. Always wrap in try/catch and have a fallback.
try {
await smtp.emails.send({
from: '[email protected]',
to: user.email,
subject: 'Welcome!',
html: template,
});
} catch (error) {
// Log it, but do not crash the app
console.error('Email send failed:', error);
// Queue for retry
await retryQueue.add('email-retry', { to: user.email, template: 'welcome' });
}
3. Use Templates, Not Inline HTML
Hardcoded HTML in your application code is a maintenance nightmare.
// Bad
await smtp.emails.send({
html: '<div style="font-family: Arial"><h1>Welcome ' + name + '</h1></div>',
});
// Good: use a template
await smtp.emails.send({
template_id: 'welcome',
variables: { name: user.name },
});
4. Validate Email Addresses Before Sending
Sending to invalid addresses hurts your sender reputation. Validate at the point of collection.
- Check format (basic regex is fine)
- Reject disposable email domains
- Consider email verification services for critical flows
5. Set Up Webhooks
Do not poll the API to check email status. Use webhooks to get notified in real-time.
// Your webhook endpoint
app.post('/webhooks/email', (req, res) => {
const event = req.body;
switch (event.type) {
case 'delivered':
updateEmailStatus(event.email_id, 'delivered');
break;
case 'bounced':
handleBounce(event.email_id, event.recipient);
break;
case 'complained':
unsubscribeUser(event.recipient);
break;
}
res.sendStatus(200);
});
6. Monitor Your Sending
Track these metrics:
- Delivery rate - Should be above 98%
- Bounce rate - Should be below 2%
- Complaint rate - Should be below 0.1%
- Open rate - Varies by email type (transactional should be 60%+)
If any of these drift, investigate immediately before it affects your sender reputation.
7. Use Separate Domains for Different Email Types
Do not send marketing and transactional emails from the same domain. If your marketing emails get flagged, your transactional emails suffer too.
transactional: [email protected]
marketing: [email protected]
Key Takeaways
- Queue emails, never send synchronously
- Handle errors and implement retry logic
- Use templates for maintainability
- Validate addresses before sending
- Set up webhooks for delivery tracking
- Monitor your metrics weekly
- Separate transactional and marketing domains
Ready to get started?
Start sending transactional email today. Free to start, no credit card required.
Get Started for FreeRelated Posts
The Best Free SMTP Services for Developers in 2026
Ten free SMTP services compared for apps, CMSs and devices: free-tier limits, daily caps, ports and TLS. Every number checked on the provider's own pages.
Best Transactional Email Services for SaaS in 2026
SMTPfast, Mailtrap, Postmark, Twilio SendGrid and Amazon SES compared for SaaS products: free tiers, real prices, inbound email, and the tradeoffs each one makes.