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
- IP warmup schedule for new sending servers
- Microsoft SNDS walkthrough
- Gmail postmaster tools walkthrough
- Sender reputation monitoring
- Domain warmup
8 bình luận