Skip to content

Multi-Server Rotation in AcelleMail — How the Dispatcher Picks

Once you have 2+ sending servers, the AcelleMail dispatcher distributes per-message across them. This guide explains the rotation logic, how to verify it in the admin pool, and how to override for deterministic routing.

How the dispatcher picks a server per message

When you launch a campaign with multiple servers in your plan's pool, AcelleMail's send-pipeline picks one server per message. The pick order:

  1. Filter by plan — only servers attached to the campaign owner's plan are candidates
  2. Filter by quota — servers that hit their daily/hourly cap drop out for this window
  3. Filter by warmup state — servers in active warmup get priority for low-volume sends and are skipped for high-volume burst sends
  4. Round-robin within remaining candidates — even distribution; no stickiness per recipient or per campaign

The pick happens at job-handler time (not at campaign-launch time). Mid-send, if one server hits quota or fails its health check, subsequent messages skip it automatically — no manual failover.

Verify the rotation in the admin pool

Open the sending-server detail

In AcelleMail's sidebar, click Sending → Sending servers. The list shows every server connected to this account with its status chip, sending limit, and last activity:

Customer sending-server list

Click into the row you want to configure. The detail page surfaces Connection settings (host / credentials), Configuration (server name, default from, sending limit, bounce + FBL handler), and the Test connection / Send test email buttons in the toolbar:

Server detail — Connection + Configuration

For pool-wide visibility, open the admin view:

Admin pool — total / active / inactive + per-type breakdown

The "Server types" bar shows the composition of your pool. The per-server row shows daily / hourly usage. After launching a campaign, refresh every few seconds — usage counters increment across multiple servers, confirming rotation is active.

Deterministic routing — when you need it

Round-robin is the right default. Some scenarios want deterministic routing:

Scenario Solution
Marketing on IP A, transactional on IP B Two Plans: "Marketing" attaches Server A only; "Transactional" attaches Server B only. Assign customers/campaigns to the right plan.
EU customers sent from EU server (GDPR data residency) Per-customer Plan assignment based on region tag
New IP being warmed — start at 10% traffic Per-server warmup config sets daily cap that grows automatically
Campaign with extra-strict deliverability requirements Attach to a Plan whose pool is a single high-reputation server

Setting it up via Sending Plans

In the admin sidebar Plans → [plan] → Sending Servers, attach the specific servers you want this plan's customers to use. Customers on this plan only see those servers; the dispatcher picks among them.

The admin server detail shows which plans each server is attached to:

Admin server detail — plan attachments visible

Common UI signals + fixes

Symptom Likely cause UI fix
All campaigns hit Server A, B sits idle Server B not attached to the plan, OR Server B's daily quota set to 0 Admin → Plan → Sending Servers (attach); OR Server B → Sending limit (raise from 0)
Server A usage hits 100% daily quota at noon Pool too small for daily volume Raise per-server quotas OR add a third server
Rotation seems uneven (60/40 split) One server is warming (lower quota) Expected — the dispatcher avoids overloading the warming server
Mid-campaign one server flatlines Health check failing — connection refused or auth error Open that server's detail → Test connection → fix the credentials/network
Campaign log shows "Used Server X" for ALL messages Single-server plan attached, OR all-but-one server disabled Confirm via Admin → Plan; enable additional servers in plan attachment

Distribution patterns over time

Healthy multi-server distribution over a 30-day window should look like:

Pattern What it means
33/33/34 across 3 servers Healthy round-robin, all servers similar quota + warmup state
80/15/5 across 3 servers One large + two warming. Expected during ramp-up.
60/40 across 2 servers Server B has a lower daily cap or recently warmed up. Adjust caps to align.
100/0 across 2 servers Server B disabled or out of the plan. Bug — fix.
Advanced: weighted rotation, sticky routing, and quota-orchestration patterns

AcelleMail's default round-robin is uniform. For non-uniform distribution patterns, the lever is per-server sending limit + how plans attach:

Weighted rotation via quota — to send 70% on Server A and 30% on Server B, set:

Server A sending_limit: 70,000/day
Server B sending_limit: 30,000/day

Pool dispatcher continues round-robin but Server B caps at 30k, after which only A receives more. Approximates a 70/30 weight at high volumes; can drift at low volumes due to round-robin.

Sticky routing per recipient — out of the box AcelleMail does NOT stick a recipient to a specific server. For sender-domain consistency (some receivers warm to a specific IP), the workaround is one-IP-per-tenant: create a separate Plan per tenant, each with a dedicated server. Operationally heavy; only worth it for high-stakes tenants.

Quota orchestration across vendors — for very high volume, the typical pattern is:

Tier 1 (highest reputation, lowest cost):  Amazon SES — 60% of volume
Tier 2 (mid reputation, growing):          Mailgun  — 25%
Tier 3 (newest IP, in warmup):             Postmark — 15%

Adjust quotas weekly as warmup-tier servers earn reputation. Auto-grow Postmark from 15% → 25% as bounce rate stays clean.

Automated rebalancing via API:

# Daily script: read per-server bounce rate, raise quota on clean + lower on dirty
for server_uid in $SERVER_UIDS; do
  br=$(curl -sH "Authorization: Bearer $ADMIN_TOKEN" \
    "https://acellemail.com/api/v1/admin/sending-servers/${server_uid}/stats" \
    | jq '.bounce_rate_last_24h')

  current=$(curl -sH "Authorization: Bearer $ADMIN_TOKEN" \
    "https://acellemail.com/api/v1/admin/sending-servers/${server_uid}" \
    | jq '.sending_limit')

  # If bounce rate < 1%, raise quota 10%; if > 3%, cut quota 25%
  new=$(python -c "
  br=$br; c=$current
  print(int(c*1.1) if br<0.01 else int(c*0.75) if br>0.03 else c)
  ")

  curl -X PATCH -H "Authorization: Bearer $ADMIN_TOKEN" \
    -d "{\"sending_limit\": $new}" \
    "https://acellemail.com/api/v1/admin/sending-servers/${server_uid}"
done

Run as a daily cron. Self-tuning pool that prefers clean servers, throttles dirty ones automatically.

Failure-mode rotation — when a server fails mid-send, AcelleMail's dispatcher marks it degraded and skips it for retries within the same campaign run. Re-evaluates per-server every 5 minutes via health-check ping. Tune the health-check interval in config/sending-server.php if you need faster failover (cost: more probe traffic).

Related articles

13 bình luận

9 bình luận

  1. ravi.kumar.del…
    if youre warming a new ip after a known issue, consider seeding with transactional mail first (password resets, order confirmations). higher engagement rate per send than marketing — helps the reputation ramp.
  2. lucas.bernard.…
    Bookmarked. Going to share with the team — we've been winging warmup and it shows in the numbers.
  3. ahmed.hassan.c…
    We warmed up a dedicated IP last fall. The 2-week ramp this article describes is on the aggressive side — Gmail in particular punishes anything faster than ~3-4 weeks. We did 4 weks and had a clean ramp...
    1. admin
      solid case study material here. if you're open to it, we'd love to write this up as a blog post — happy to credit you anonymously or otherwise.
  4. jmorrison.itop…
    the Postmaster Tools section is gold. Most senders don't even kow it exists
  5. sobrien.kw
    we hit a spamhaus listing once. self-service delisting was actually fast (< 24h) but the reputation recovery took weeks. not the listing itself that hurt — the user complaints that caused it.
  6. lequan.saigon
    This is the clearest IP warmup schedule I've found. The volume table at the top is what I'm referencing daily.
    1. admin
      Appreciate it. If anything in this needs updaing, ping us — we revisit articles every few months.
  7. linhvu.dev
    confirming the Postmaster Tools data lag — sometimes 48 hours, sometimes longer. Don't make decisions on a single day's data.
  8. joel.anders.se
    For very low-volume senders (< 5k/month), does warmup even matter? Or just send and let the provider's shared pool absorb the trickle?
    1. admin
      Good question. The campaign:rerun audit writes to laravel.log only when the audit decides to force-resume — pure noop runs are silent. We'll add an info-level heartbeat in a future Acelle release to make it easier to monitor
  9. emma.whitaker
    Does engagement-based segmentation help during warmup? E.g. only sending to the most-engaged 0% during week 1?
    1. admin
      Same answer as above for SaaS-tenant — works the same way per-tenant, with the caveat that the cron must be set per-customer (not just system-wide)

More in Sending & Deliverability