DEV Community

Dhiraj Chatpar
Dhiraj Chatpar

Posted on

ip-warmup-strategies-2026.md

Why IP Warmup Matters in 2026

Gmail, Yahoo, and Microsoft apply machine learning reputation models to every sending IP. These models evaluate:

  • Volume trajectory — Sudden spikes trigger abuse filters
  • Complaint rate — >0.1% complaints gets you throttled or blocked
  • Bounce rate — Hard bounces damage reputation faster than soft bounces
  • Engagement rates — Opens, clicks, and reply rates signal legitimacy
  • Authentication status — SPF, DKIM, and DMARC alignment affect trust scoring

New IPs have no history, so every ISP treats them as potentially malicious until proven otherwise. The warmup process builds that proof systematically.


ISP-Specific Warmup Requirements

Gmail (Google Workspace / Gmail.com)

Gmail is the largest single mailbox provider in the world. Gmail's reputation system is the strictest — a botched Gmail warmup affects your deliverability for 60-90 days.

Gmail warmup schedule (recommended 8-week ramp):

Week Daily Volume Notes
1 50-100 msgs/day Only highly engaged recipients (opened in last 30 days)
2 200-500 msgs/day Continue engaged users, watch complaint rate
3 1,000-2,000 msgs/day Add moderately engaged users
4 5,000-10,000 msgs/day Monitor Gmail Postmaster Tools daily
5 25,000-50,000 msgs/day Check spam rate < 0.1%, complaint rate < 0.05%
6 100,000-200,000 msgs/day ISP trust building phase
7 400,000-800,000 msgs/day Approach full volume
8 Full volume Continuous monitoring via Postmaster Tools

Critical Gmail requirements:

  • SPF, DKIM, and DMARC must all pass before starting warmup
  • Use Gmail Postmaster Tools to monitor reputation in real time
  • If complaint rate exceeds 0.1%, pause immediately and investigate

Microsoft 365 / Outlook / Hotmail

Microsoft's Smart Network Data Services (SNDS) and Outlook.com's filtering are slightly more forgiving than Gmail, but still require systematic warmup.

Microsoft warmup approach:

  • Similar 8-week schedule to Gmail
  • Monitor via SNDS (snds.azurewebsites.net) — free IP reputation data
  • Outlook.com complaint threshold: 0.1% (same as Gmail)
  • Microsoft's filtering is more sensitive to hard bounces than soft

Yahoo Mail

Yahoo's filtering improved significantly in 2024-2025 with their mandatory DMARC requirements. Yahoo uses complaint rate as the primary reputation signal.

Yahoo warmup:

  • 6-week ramp is sufficient for most senders
  • Monitor via Yahoo Postmaster (postmaster.yahoo.com)
  • Complaint rate must stay below 0.1%
  • Yahoo is more tolerant of volume spikes than Gmail

Apple Mail (iCloud)

Apple's Mail Privacy Protection (MPP) introduced in 2021 changed how Apple measures engagement. MPP sends opens automatically, which means Apple-based open rates are inflated and unreliable for reputation.

Apple-specific considerations:

  • Focus on click rates rather than open rates for Apple recipients
  • Apple's filtering is generally lenient for legitimate senders
  • High complaint rates from Apple users will still trigger filtering

Automated KumoMTA Warmup Lua Policy

This is a production-ready Lua policy for KumoMTA that implements automated IP warmup with adaptive throttling:

-- /etc/kumomta/warmup_policy.lua
-- Automated IP warmup for KumoMTA

-- Warmup schedule: messages per day by week
local WARMUP_SCHEDULE = {
    week1 = 100,
    week2 = 500,
    week3 = 2000,
    week4 = 10000,
    week5 = 50000,
    week6 = 200000,
    week7 = 800000,
    week8 = nil, -- nil = full volume, based on ISP feedback
}

-- IP pool for rotation during warmup
local WARMUP_IPS = {
    "203.0.113.1",
    "203.0.113.2",
    "203.0.113.3",
    "203.0.113.4",
}

-- Track warmup state per IP
local warmup_state = {}

local function get_warmup_week(ip)
    if not warmup_state[ip] then
        warmup_state[ip] = { week = 1, start_time = os.time(), daily_sent = 0 }
    end
    return warmup_state[ip]
end

local function should_advance_week(ip)
    local state = warmup_state[ip]
    if not state then return false end

    local week_duration = 7 * 24 * 3600 -- 7 days
    local elapsed = os.time() - state.start_time

    return elapsed >= week_duration and state.week < 8
end

local function advance_warmup_week(ip)
    local state = warmup_state[ip]
    if state.week < 8 then
        state.week = state.week + 1
        state.start_time = os.time()
        state.daily_sent = 0
        log_info("IP " .. ip .. " advancing to week " .. state.week)
    end
end

local function get_daily_limit(ip)
    local state = get_warmup_week(ip)
    local week_key = "week" .. state.week
    local limit = WARMUP_SCHEDULE[week_key]

    if limit == nil then
        return nil -- Full volume (no limit)
    end

    return limit
end

-- Main policy: apply warmup limits
kumo.on("smtp_message_received", function(domain, meta)
    local sending_ip = meta.sending_ip or "unknown"

    -- Check if warmup should advance
    if should_advance_week(sending_ip) then
        advance_warmup_week(sending_ip)
    end

    -- Apply daily limit
    local limit = get_daily_limit(sending_ip)
    if limit then
        local state = get_warmup_week(sending_ip)
        if state.daily_sent >= limit then
            log_warn("Warmup limit reached for " .. sending_ip .. ": " .. limit .. " daily limit")
            kumo.defer_message("Warmup in progress, try again tomorrow")
            return
        end
        state.daily_sent = state.daily_sent + 1
    end

    -- Rotate sending IP in pool (round-robin)
    local ip_index = (tonumber(sending_ip:match("%d+$")) or 1) % #WARMUP_IPS + 1
    kumo.set_sending_ip(WARMUP_IPS[ip_index])
end)

-- Adaptive throttling based on 4xx responses
kumo.on("smtp_delivery_result", function(result, meta)
    local sending_ip = meta.sending_ip or "unknown"

    if result.code == 421 or result.code == 429 then
        -- ISP throttling — reduce volume by 50% for this IP
        local state = warmup_state[sending_ip]
        if state then
            state.daily_sent = math.floor(state.daily_sent * 0.5)
            log_warn("ISP throttling detected for " .. sending_ip .. ", reducing volume")
        end
    end

    if result.code >= 500 then
        -- Hard bounce — remove from pool, alert
        log_error("Hard bounce from " .. sending_ip .. ": " .. result.code)
        remove_ip_from_pool(sending_ip)
        alert_ops("Hard bounce IP " .. sending_ip .. " removed from warmup pool")
    end
end)
Enter fullscreen mode Exit fullscreen mode

Load this policy in your kumomta.conf:

kumo.load_policy_file("/etc/kumomta/warmup_policy.lua")
Enter fullscreen mode Exit fullscreen mode

Traffic Shaping During Warmup

Traffic shaping during warmup is critical. Sending too fast triggers ISP throttling; sending too slowly delays building reputation. The goal is consistent, predictable volume growth.

Key traffic shaping parameters:

-- KumoMTA traffic shaping during warmup
kumo.on("smtp_message_received", function(domain, meta)
    local sending_ip = meta.sending_ip

    -- Maximum messages per minute per IP (prevents accidental spikes)
    kumo.limit_sending(sending_ip, 50, { per = "minute" }) -- Week 1
    -- Week 2: 200/min, Week 3: 1000/min, etc.
end)

-- Per-ISP connection limiting
-- Some ISPs (notably Gmail) throttle based on connection count
kumo.on("smtp_delivery_start", function(domain, meta)
    if string.find(domain, "gmail.com") then
        kumo.limit_connections_per_remote("gmail.com", 10)
    elseif string.find(domain, "outlook.com") or string.find(domain, "microsoft.com") then
        kumo.limit_connections_per_remote("outlook.com", 15)
    end
end)
Enter fullscreen mode Exit fullscreen mode

Monitoring During Warmup

Gmail Postmaster Tools

Free tool at postmaster.google.com. Shows:

  • Reputation per sending domain/IP
  • Spam rate
  • Authentication results (SPF/DKIM/DMARC pass rates)
  • Encryption status

Microsoft SNDS

Free at snds.azurewebsites.net. Shows:

  • IP reputation (Good, Neutral, Bad)
  • Complaint rate
  • Mail volume trends

Internal Metrics to Track

Metric Target Alert
Hard bounce rate < 2% > 3% → pause
Soft bounce rate < 5% > 10% → investigate
Complaint rate < 0.1% > 0.1% → pause
Delivery latency p95 < 30s > 60s → investigate
4xx deferral rate < 10% > 20% → reduce volume

Warmup Rollback Procedures

If something goes wrong during warmup:

Step 1: Pause sending immediately

-- Emergency pause in policy
local EMERGENCY_PAUSE = true

kumo.on("smtp_message_received", function(domain, meta)
    if EMERGENCY_PAUSE then
        kumo.defer_message("Warmup emergency pause")
        return
    end
end)
Enter fullscreen mode Exit fullscreen mode

Step 2: Diagnose the issue

  • Check bounce codes — which ISPs are bouncing?
  • Check complaint rates — which campaigns triggered complaints?
  • Check authentication — are SPF/DKIM/DMARC all passing?

Step 3: Fix and resume

  • Address the root cause (list quality, authentication, content)
  • Resume at 50% of last successful daily volume
  • Monitor for 48 hours before increasing

Step 4: Document

  • Log what went wrong and what you changed
  • Update your warmup policy to prevent recurrence

Common Warmup Mistakes

Mistake 1: Starting Warmup Without Authentication

Never begin warmup without SPF, DKIM, and DMARC fully configured. ISPs evaluate authentication as part of reputation building — sending unauthenticated email during warmup is counterproductive.

Mistake 2: Mixing New and Established IPs

Don't send from a fresh IP alongside IPs with established reputation. If one new IP gets flagged, it can affect the whole sending infrastructure.

Mistake 3: Sending to Cold Lists

Only send to engaged recipients during warmup. Purchased lists, scraped lists, or cold outreach contacts will generate complaints and bounces that destroy reputation.

Mistake 4: Ignoring 4xx Deferrals

A sudden increase in 4xx responses means an ISP is throttling you. If you ignore it and keep sending, you'll get a 5xx (permanent failure) and potentially blacklisted.

Mistake 5: Rushing the Schedule

Week 1 at 100 messages is not arbitrary — it's calibrated to what ISPs expect. Compressing an 8-week schedule into 2 weeks will get you throttled.


FAQ

Q: Can I start warmup with just 1 IP?
A: Yes, but 2-4 IPs is better. Rotating across IPs during warmup builds reputation faster and provides redundancy if one IP gets flagged.

Q: What if I need to send volume immediately?
A: Rent established IPs from a reputation broker (e.g., Kickbox, 250ok). These IPs come with pre-built reputation, reducing warmup time from 8 weeks to 1-2 weeks. This is expensive but sometimes necessary for product launches.

Q: Does warmup apply when migrating MTAs?
A: Yes. Any new sending IP — regardless of whether you're migrating from PowerMTA to KumoMTA — needs warmup. Your historical reputation does not transfer to new IPs.

Q: How do I know when warmup is complete?
A: When you're at full planned volume, your bounce rate is stable (< 2%), complaint rate is < 0.1%, and Gmail Postmaster Tools shows "Strong" reputation for your domain — typically after 8 weeks of consistent volume growth.

Q: Can I automate warmup with PowerMTA?
A: PowerMTA's warmup is manual — you'd configure IP pool limits and adjust XML config weekly. KumoMTA's Lua-based policy automates this entirely, including automatic advancement and rollback on errors.


Get Help With IP Warmup

PostMTA manages IP warmup for enterprise senders as part of our managed email infrastructure service. We handle:

  • Complete warmup schedule design based on your volume and ISPs
  • KumoMTA or PowerMTA warmup policy configuration
  • Real-time monitoring via Postmaster Tools and SNDS
  • Emergency rollback and re-warmup if issues occur

👉 Talk to a deliverability specialist →

For related guides, see KumoMTA Setup Guide, Email Authentication Setup, and Bounce Rate Reduction Guide.

Top comments (0)