Prompt
How do I route email sending for a multi-tenant platform?
Latest observation
A good multi-tenant email setup usually means separating who owns the message, what brand it should look like, and which delivery path/credentials to use.
1) Decide the tenancy model for email
There are usually 3 patterns:
A. Shared sending infrastructure, tenant-specific branding
- One email service provider account or cluster
- Each tenant has:
- from name/address
- reply-to
- templates/branding
- possibly custom domain for tracking links
- Best when tenants don’t need isolated deliverability
B. Separate sending domains/accounts per tenant
- Each tenant gets:
- its own sending domain
- SPF/DKIM/DMARC
- optionally its own ESP account/subaccount
- Best for enterprise tenants or strict deliverability/isolation requirements
C. Hybrid
- Default tenants use shared infrastructure
- Large/high-volume tenants get dedicated domains or subaccounts
- This is often the most practical approach
2) Use an internal “email routing” layer
Don’t send directly from business logic. Put a routing service or module in between:
App event → email job → routing layer → provider/account → delivery
This layer should determine:
- tenant ID
- email type (transactional, notification, marketing, system)
- recipient locale/region
- sending identity
- provider/subaccount
- template
3) Route by tenant configuration
Store per-tenant settings like:
tenant_idemail_providerorprovider_account_idfrom_namefrom_emailreply_tosending_domaintracking_domaintemplate_brandingregionenabled_email_types
Example routing decision:
if tenant has dedicated provider account:
send through tenant account
else:
send through shared account with tenant-specific from/reply-to
4) Separate transactional vs marketing
This is important for deliverability and compliance.
- Transactional emails: password resets, receipts, alerts
- should be highly reliable
- usually sent immediately
- Marketing emails: newsletters, promotions
- should go through consent checks
- often different provider path, suppression lists, and throttling
Many platforms use:
- one route for transactional
- another route for marketing
5) Handle sender identity correctly
For best inboxing:
- Use a verified sending domain per tenant if possible
- Align:
- SPF
- DKIM
- DMARC
- Avoid using a shared “from” domain for many unrelated tenants if branding matters
- Ensure the reply-to goes to the tenant or a tenant-specific mailbox
6) Design for isolation and safety
At minimum, enforce:
- tenant-scoped templates
- tenant-scoped recipient lists
- tenant-scoped suppression lists
- tenant-scoped rate limits
- tenant-scoped audit logs
Also prevent:
- tenant A sending as tenant B
- cross-tenant template access
- accidental mixing of provider credentials
7) Add failover and retry logic
Your routing layer should support:
- retries with backoff
- dead-letter queue for permanent failures
- fallback provider if allowed
- provider health checks
For example:
- primary ESP: SendGrid
- secondary ESP: SES
- fallback only for transactional mail
8) Consider regional routing
If tenants are tied to regions or data residency:
- route EU tenants through EU infrastructure
- route US tenants through US infrastructure
- keep logs and content storage region-aware
9) Recommended implementation pattern
A common architecture:
- Application generates email event
- Queue stores job with
tenant_id,email_type,template_id,payload - Routing service loads tenant config
- Template renderer applies tenant branding
- Provider adapter sends email
- Delivery events/webhooks update status
- Bounce/complaint handling updates suppression lists per tenant
10) Practical recommendation
If you’re starting out:
- Use one ESP
- Build a tenant-aware routing layer
- Support per-tenant from/reply-to/template branding
- Add dedicated domains/subaccounts later for larger tenants
That gives you a clean path from simple to enterprise-grade.
If you want, I can also show:
- a database schema for tenant email routing,
- a sample routing function in code,
- or an architecture diagram for this setup.