At small scale, one sending server is enough. At medium scale (500k+/month), one is a single point of failure for both volume and reputation — a single bad campaign or one misbehaving subscriber can throttle the whole program. The defense is multi-server rotation: route traffic to different sending servers based on its risk profile, isolating reputation between traffic classes so a problem in one doesn't propagate to all.
This article covers the four canonical rotation patterns, the AcelleMail configuration that implements each, and the operational considerations.
Pattern 1 — By intent (most common)#
Split sending by message intent:
- Transactional — receipts, password resets, account notifications. Highest engagement, lowest complaint.
- Marketing — warm audience — engaged subscribers, < 60 days since last open.
- Marketing — cold audience — re-engagement, low-engagement, dormant subscribers.
Each goes through a different sending server (and ideally a different IP):
Admin → Sending Servers:
"SES-Transactional" (1 dedicated IP) — quota 100k/day, throttle 50/sec
"SES-Marketing-Warm" (1-2 dedicated IPs) — quota 500k/day, throttle 100/sec
"SES-Marketing-Cold" (1 dedicated IP) — quota 100k/day, throttle 25/sec
Customers → <customer> → Configure default sending-server per intent
The reputation isolation: a complaint storm on a re-engagement campaign hits SES-Marketing-Cold's IP. SES-Transactional's IP — and your password-reset deliverability — is untouched.
This is the most-impactful single rotation pattern. If you implement only one rotation pattern, make it this one.
Pattern 2 — By ISP#
Route per recipient's mailbox host:
Admin → Sending Servers:
"SES-Gmail" — for *@gmail.com / *@googlemail.com
"SES-Microsoft" — for *@outlook.com / *@hotmail.com / *@live.com / *@msn.com
"SES-Other" — everything else
Implementation in AcelleMail uses list-server-recipient-domain routing — when a campaign sends, the worker picks the sending server based on the recipient's email domain. Configure via:
Customers → <customer> → Lists → <list> → Sending Server Mapping
gmail.com → SES-Gmail
googlemail.com → SES-Gmail
outlook.com → SES-Microsoft
...
default → SES-Other
The benefit: a Gmail reputation event (Postmaster IP rep drops Medium → Low) doesn't affect Outlook deliverability. You can recover Gmail traffic by routing to a fresh IP without disturbing Microsoft/Yahoo/etc.
The cost: more sending servers (more dedicated IP cost), more routing logic to maintain.
Use this pattern at high scale (5M+/month) where ISP-isolation matters more than IP cost.
Pattern 3 — By warmup state#
When introducing new IPs (per the warmup schedule):
Admin → Sending Servers:
"SES-Hot" — fully-warmed IP, 100% production traffic
"SES-Warming" — new IP being warmed; quota = today's warmup target
"SES-On-Deck" — next IP to be warmed; not in active rotation yet
Pattern:
- Warming IP gets engagement-only traffic — most-engaged segment of your list, daily volume per the warmup schedule.
- Hot IP gets the rest — broad list, full daily volume.
- Once Warming reaches "High" reputation at all major ISPs, it graduates to Hot. The previous Hot becomes a backup; or rotated out for upgrade if older.
This keeps the warmup schedule clean — you're not mixing warming volume with production volume on the same IP.
Pattern 4 — By recipient timezone#
For B2C senders with global audiences:
Admin → Sending Servers:
"SES-Asia" — sends during Asia business hours (UTC+8 zone)
"SES-Europe" — sends during Europe business hours
"SES-Americas" — sends during Americas business hours
Combined with AcelleMail's "Send by recipient timezone" mode (see throttling strategies), each region's traffic is dispatched from a region-appropriate IP. Benefits at very-high scale: avoids 100 % of global daily traffic landing in a single 4-hour window from a single IP, which would trip every receiver's rate-protection.
Most operators don't need this until 5M+/month with > 50 % non-Americas audience.
Multi-server health monitoring#
With N servers in rotation, you need per-server visibility:
-- Daily per-server health for the last 7 days
SELECT
ss.name,
DATE(tl.created_at) as day,
COUNT(*) as sent,
SUM(CASE WHEN bl.bounce_type = 'hard' THEN 1 ELSE 0 END) as hard,
SUM(CASE WHEN bl.bounce_type = 'soft' THEN 1 ELSE 0 END) as soft,
SUM(CASE WHEN bl.bounce_type = 'unknown' THEN 1 ELSE 0 END) as complaints,
ROUND(SUM(CASE WHEN bl.bounce_type = 'hard' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 2) as hard_pct,
ROUND(SUM(CASE WHEN bl.bounce_type = 'unknown' THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 3) as compl_pct
FROM tracking_logs tl
JOIN sending_servers ss ON tl.sending_server_id = ss.id
LEFT JOIN bounce_logs bl ON bl.tracking_log_id = tl.id
WHERE tl.created_at > NOW() - INTERVAL 7 DAY
GROUP BY ss.id, day
ORDER BY ss.name, day;
Wire to a Slack alert when any server's compl_pct > 0.30 or hard_pct > 3.0 for ≥ 2 days running.
Failover within a rotation pattern#
When one server in rotation fails (auto-paused by pauseOnNegativeSignals, or admin-paused), reroute its traffic to a backup. The pattern:
Customers → <customer> → Sending Server Failover:
Primary: SES-Marketing-Warm
Failover: SES-Other (secondary; less-isolated but functional)
When primary is paused, new sends auto-route to failover. Keep failover IP reputation distinct — don't make Pattern-2 ISP-Gmail's failover be Pattern-2 ISP-Microsoft, or you'll cross-contaminate reputation.
When NOT to rotate#
- At hobby/small scale (< 50k/month). One server is fine; rotation overhead exceeds benefit.
- For pure transactional senders (no marketing). The "by intent" pattern collapses to "all transactional"; one server is correct.
- When you're warming the only IP you have. Don't introduce a second IP simultaneously; warm one fully first.
Related reading#
FAQ#
How many dedicated IPs do I need?#
Roughly: 1 per intent class for Pattern 1 (so 3 IPs for transactional + warm + cold), or 1 per major ISP for Pattern 2. SES dedicated IPs at $25/month make 3 IPs = $75/month — usually worth it at 500k+/month.
Can I run rotation with shared SES IPs?#
Pattern 1 and Pattern 4 work somewhat with shared IPs (different SES regions = different IP pools). Pattern 2 and Pattern 3 require dedicated IPs to be meaningful.
What if all servers are paused?#
Then sending is fully halted — which is the correct state for an extreme reputation event. Investigate before un-pausing; don't override blindly. AcelleMail will queue messages waiting for a server to become available.
How do I migrate a single-server setup to rotation?#
Add the new sending servers, configure per-list/per-intent assignment, but keep the original server in the rotation as the "default." Migrate one customer (or one list) at a time, monitor for 7 days, then expand.
A reference 4-IP setup at the Medium tier#
For an AcelleMail program at 2-3M sends/month with mixed transactional + marketing audience:
| Sending server |
IP type |
Daily quota |
Throttle |
Audience |
tx-dedicated |
Dedicated SES IP |
200,000 |
80/sec |
Transactional only (receipts, password resets, account events) |
mkt-warm-dedicated |
Dedicated SES IP |
1,500,000 |
200/sec |
Marketing — engaged 60-day segment |
mkt-cold-dedicated |
Dedicated SES IP |
200,000 |
30/sec |
Marketing — re-engagement, dormant subscribers |
mkt-bulk-shared |
SES shared pool |
unlimited |
100/sec |
Promotional broadcasts, newsletter — broad list |
Total fixed cost: 3 × $25/month for dedicated IPs = $75/month, plus per-message SES fees (~$0.10 per 1,000) which scale linearly with volume.
The reputation isolation pays for itself the first time a marketing-cold campaign trips a complaint storm — the transactional IP is unaffected, password resets keep delivering, support tickets don't pile up from "I never got the reset email." That single incident-prevention case is worth several months of dedicated-IP fees.
Operational runbook for adding a new sending server#
The 30-minute checklist when expanding rotation:
- Provision the IP (SES dedicated allocation, ~5 min).
- Reverse DNS PTR — confirm the upstream is publishing PTR matching your sending hostname. Without PTR, Microsoft and some Yahoo paths grey-list immediately.
- DKIM identity in SES — add the sending domain to SES's "Verified Identities" with the new IP pool.
- AcelleMail sending server entry — Admin → Sending Servers → New, point at the new SES configuration set.
- Initial test send — 10 messages to seed addresses, confirm delivery + headers (DKIM-Signature, Authentication-Results).
- Add to warmup strategy — assign the WarmupStrategy with
startingVolume = 50 and the appropriate ramp.
- Add to per-customer assignment — start with one low-volume customer for the first week of warmup.
- Monitor SNDS + Postmaster daily — watch for the IP appearing in dashboards (24-48h delay).
- Graduate from warmup when the warmup completion criteria are met.
- Add to broader rotation — assign to more customers or remove the warmup-segment restriction.
Don't skip steps 2 and 3 — both are silent failures that surface only after several days of degraded deliverability.