Why per-ISP warmup beats uniform warmup#
Receiving servers weight your reputation differently. Send 50k emails on Day 14 of warmup:
- Gmail may accept all 50k inbox if engagement is high (Gmail rewards engagement fast)
- Outlook treats it as a spike; routes 30% to Junk (Microsoft is volume-sensitive)
- Yahoo sees an unfamiliar pattern; routes 60% to Junk (Yahoo is conservative)
- iCloud silently drops 40% (Apple is strictest, gives least feedback)
A uniform warmup curve optimized for Gmail under-warms Outlook/Yahoo/iCloud. A uniform curve optimized for the slowest (iCloud) wastes Gmail's appetite. Per-ISP warmup matches each receiver's curve.
Per-ISP recommended curves#
| Day |
Gmail (% of full) |
Outlook |
Yahoo |
iCloud |
| 1 |
5% (high engagement target) |
1% |
1% |
0.5% |
| 3 |
15% |
3% |
2% |
1% |
| 7 |
40% |
10% |
5% |
3% |
| 14 |
75% |
30% |
15% |
8% |
| 21 |
100% |
60% |
35% |
20% |
| 30 |
100% |
90% |
70% |
50% |
| 45 |
100% |
100% |
100% |
100% |
If your audience is 50% Gmail + 30% Outlook + 15% Yahoo + 5% iCloud (typical US mix), uniform warmup at Day 14 = 75% volume. Per-ISP at Day 14 = ~52% volume but ~85% inbox-placement across receivers, vs ~65% uniform. Net more delivered.
Implementation in AcelleMail#
Tag subscribers by ISP#
The per-ISP segment lives in tags. Apply at import-time or via batch update:
-- Run once via tinker / migration to tag existing subscribers
UPDATE subscribers SET tags = JSON_ARRAY_APPEND(COALESCE(tags, JSON_ARRAY()), '$', 'isp:gmail')
WHERE email REGEXP '@(gmail|googlemail)\.com$';
UPDATE subscribers SET tags = JSON_ARRAY_APPEND(COALESCE(tags, JSON_ARRAY()), '$', 'isp:outlook')
WHERE email REGEXP '@(outlook|hotmail|live|msn)\.com$';
UPDATE subscribers SET tags = JSON_ARRAY_APPEND(COALESCE(tags, JSON_ARRAY()), '$', 'isp:yahoo')
WHERE email REGEXP '@(yahoo|ymail|aol)\.com$';
UPDATE subscribers SET tags = JSON_ARRAY_APPEND(COALESCE(tags, JSON_ARRAY()), '$', 'isp:icloud')
WHERE email REGEXP '@(icloud|me|mac)\.com$';
For ongoing imports, add the tag-by-ISP step to your import pipeline OR use AcelleMail's import wizard's tag-mapping feature.
Create per-ISP segments#
In your list, Segments → New segment with rule:
Tag contains 'isp:gmail'
Repeat for outlook, yahoo, icloud.
Daily warmup campaign per ISP#
Day 7 example: send to gmail-segment at 40% volume.
- New campaign → recipients = gmail segment only
- Sending limit = the day's gmail % × your full-volume target
- Launch
Repeat with smaller volumes per outlook + yahoo + icloud segments same day.
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:

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:

Where the throttle lives#
Same sending-server detail → Configuration section. The Sending limit dropdown caps how many emails AcelleMail will hand to this server per unit of time (per minute / hour / day):

AcelleMail enforces the limit globally — when the rolling-window counter hits the cap, the queue holds back until the window slides. No throttling code in your campaigns; configure once per server.
Adjust the sending-limit-per-hour per-day per the curves above. As each ISP's reputation grows (verify via Postmaster Tools / SNDS / AcelleMail's per-domain bounce mining), step up that ISP's volume independently.
Use a warmup strategy preset#
AcelleMail's admin Warmup Strategies screen ships with 4 preset curves you can attach per-server — Cautious, Balanced (default), Aggressive, Long-Haul:

For per-ISP warmup, the safest pattern: attach Long-Haul to servers targeting Microsoft/Yahoo/iCloud (conservative ISPs), Balanced to gmail-targeted servers. Mix by which ISP-tagged segment the server is reserved for.
Per-ISP signal sources#
| ISP |
Reputation source |
Daily-check frequency |
| Gmail |
Google Postmaster Tools |
Daily during warmup; weekly after |
| Outlook (Microsoft) |
SNDS (Smart Network Data Services) |
Daily during warmup; weekly after |
| Yahoo |
No native postmaster — use AcelleMail bounce log per-recipient |
Daily during warmup |
| iCloud (Apple) |
No native postmaster — use bounce log per-recipient |
Daily during warmup |
| B2B (Proofpoint / Mimecast / Cisco) |
Direct relationships, OR your bounce log patterns |
Investigate per-domain on bounce |
For per-ISP AcelleMail-side mining, query your bounce_logs table:
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(email, '@', -1), '.', -2) AS domain,
COUNT(*) AS bounces,
SUM(CASE WHEN bounce_type = 'hard' THEN 1 ELSE 0 END) AS hard
FROM bounce_logs
WHERE created_at >= NOW() - INTERVAL 7 DAY
GROUP BY domain
ORDER BY bounces DESC
LIMIT 25
(Remember: prefix your table name with DB_TABLES_PREFIX if you have one — bounce_logs → acelle_bounce_logs in some installs.)
If yahoo.com bounces are 40% of all bounces but only 15% of your list, Yahoo-specific block. Pause yahoo segment; investigate at AcelleMail's Yahoo-postmaster-program contact.
Common UI signals + fixes#
| Symptom |
Likely cause |
UI fix |
| Tag-based segment shows fewer subscribers than expected |
Tag not applied at import — back-fill via SQL or re-import |
Re-tag via the SQL pattern above, or Audience → list → Import → Update mode |
| Gmail volume at Day 7 — many soft bounces |
Quota too aggressive |
Hold gmail segment at current day; don't ramp tomorrow |
| Outlook segment fully delivered, Yahoo segment 50% bounce |
Yahoo-specific reputation hit |
Pause yahoo segment for 5 days; resume at lower volume |
| Per-ISP campaign report missing breakdown |
AcelleMail's per-domain stats need a custom report |
Use campaigns/{uid}/tracking-log/listing filtered by domain |
| Setting up 4 separate campaigns each day feels manual |
Automate via API + cron |
Schedule campaigns via API; pull tag-based segments dynamically |
Advanced: automated per-ISP volume orchestration via API
For high-volume installs, manual per-ISP scheduling is tedious. Automate via API + cron.
Daily orchestration script:
#!/bin/bash
# Run at 03:00 daily. Auto-launches 4 per-ISP warmup campaigns based on
# current warmup day + per-ISP signal health.
DAY_OF_WARMUP=$1 # Pass current day as arg
ACELLE_TOKEN="..."
LIST_UID="..."
TEMPLATE_UID="..."
# Per-ISP daily volumes (from the curve table above)
declare -A GMAIL_VOL=([1]=5000 [3]=15000 [7]=40000 [14]=75000)
declare -A OUTLOOK_VOL=([1]=1000 [3]=3000 [7]=10000 [14]=30000)
declare -A YAHOO_VOL=([1]=1000 [3]=2000 [7]=5000 [14]=15000)
declare -A ICLOUD_VOL=([1]=500 [3]=1000 [7]=3000 [14]=8000)
for isp in gmail outlook yahoo icloud; do
case $isp in
gmail) vol=${GMAIL_VOL[$DAY_OF_WARMUP]} ;;
outlook) vol=${OUTLOOK_VOL[$DAY_OF_WARMUP]} ;;
yahoo) vol=${YAHOO_VOL[$DAY_OF_WARMUP]} ;;
icloud) vol=${ICLOUD_VOL[$DAY_OF_WARMUP]} ;;
esac
# Check yesterday's per-ISP signal — if bounce rate creeping up, skip today
yesterday_bounce=$(curl -sH "Authorization: Bearer $ACELLE_TOKEN" \
"https://acellemail.com/api/v1/campaigns/recent?tag=isp:$isp&days=1" \
| jq '.aggregate.bounce_rate')
if (( $(echo "$yesterday_bounce > 0.04" | bc -l) )); then
echo "Skip $isp today — yesterday bounce $yesterday_bounce"
continue
fi
# Launch today's per-ISP warmup campaign
curl -X POST "https://acellemail.com/api/v1/campaigns" \
-H "Authorization: Bearer $ACELLE_TOKEN" \
-d "{
\"name\": \"Warmup Day $DAY_OF_WARMUP — $isp\",
\"list_uid\": \"$LIST_UID\",
\"template_uid\": \"$TEMPLATE_UID\",
\"segment_tags\": [\"isp:$isp\", \"engaged-last-7d\"],
\"sending_limit\": $vol,
\"schedule\": \"now\"
}"
done
Signal-gated step-up:
Replace the manual day-counter with a signal-driven gate:
GATE: bounce <2% AND complaint <0.1% AND open >25% in last 24h for THIS isp
YES → step up volume 20%
NO → hold today's volume; if 3 consecutive hold-days, cut volume 25%
Self-tuning warmup. Run as a daily cron. Reduces manual intervention; surfaces problems via alerts rather than silent under-volume.
Multi-tenant warmup orchestration:
For SaaS operators, each tenant gets their own warmup. The orchestrator loops over active tenants:
for each tenant:
for each (tenant, ISP) pair:
fetch current warmup day
fetch per-ISP signals
launch / skip / hold today's campaign
increment tenant.isp.warmup_day on success
Tooling note — for very large warmups (>10M emails/day) consider the dedicated tools like Mailosaur or Litmus's deliverability monitoring as additional signals. Per-ISP reputation tracking at scale is a discipline of its own.
Related articles#