IP warm up is sending a small, gradually increasing volume from a new IP address or domain so that Gmail, Outlook, Yahoo and others can build a reputation for it. Start with tens of emails a day to people who expect your mail, grow over two to six weeks while bounces and complaints stay low, and hold or step back the moment placement gets worse. Perfect SPF, DKIM and DMARC do not give a new sender a reputation; only sending history does.
This applies when you move to your own self-hosted email server, buy a dedicated IP from a provider, launch a new domain, or start sending again from a domain that has been quiet for months.
What we saw on day one
When we brought our own server online, every check passed: port25's verifier reported SPF pass, DKIM pass and iprev pass. We sent two near-identical test emails, one from each of two of our domains, to the same Gmail account. One landed in the Inbox. The other landed in Spam, with Gmail's note "similar to messages identified as spam in the past".
Nothing was misconfigured. One domain simply had no sending history Gmail could use. That is normal for a brand-new or dormant domain, and it is what warm-up fixes: gradual sending to people who open, reply and do not complain.
Before you start: get the basics right
Warm-up cannot fix broken authentication. Confirm first:
- SPF, DKIM and DMARC all pass and align (how to set up DMARC covers alignment).
- The PTR, A record and HELO name match (reverse DNS for email).
- The IP is not on a real blocklist. (Careful: Spamhaus answers queries from public resolvers with
127.255.255.x, which some checkers misreport as "listed".) - Bounces are handled: addresses that hard-bounce are removed and never retried.
- Marketing mail has a one-click unsubscribe.
A starting warm-up schedule
Use this schedule as a starting point. It is not a promise of results, and every sender is different. Move to the next row only when the previous one was clean: no rise in bounces, no complaints, test messages landing in the Inbox.
| Period | Daily volume (total) | What to send |
|---|---|---|
| Days 1–3 | 5–20 | Test messages to your own accounts; replies to people who wrote to you |
| Days 4–7 | 20–50 | Transactional mail: password resets, receipts, notifications |
| Week 2 | 50–150 | All transactional mail; first small batches to your most engaged contacts |
| Week 3 | 150–500 | Recent, engaged recipients (opened or clicked in the last 30–60 days) |
| Week 4 | 500–1,500 | Wider engaged segments |
| Weeks 5–6 | Roughly double each week | Your normal mix, still excluding long-inactive addresses |
If your normal volume is small, say 50 messages a day, you are "warmed up" once you reach it with clean results, which may take only a week or two. Still get there gradually. The table matters most for senders heading into thousands per day, where a sudden jump is most visible to receivers.
Two more rules matter as much as the numbers:
- Spread across receivers. If most of your list is Gmail, a "500 a day" step means about 400 to Gmail. Keep per-provider volume growing gradually too.
- Spread through the day. A steady trickle looks better than one burst at 9 a.m.
For our own outreach domain we started at about five a day and planned two to three weeks of warm-up before normal volume.
Send the most-wanted mail first
Receivers learn from how people respond. In the first weeks, send the mail people are most likely to open and least likely to report:
- Password resets, sign-in links, receipts.
- Replies to inbound messages.
- Notifications people asked for.
- Newsletters to people who opened recently.
Leave old, unengaged addresses until the end, or drop them. Never warm up with a purchased or scraped list.
Let Postfix enforce the pace
If you run Postfix, you can make the server itself slow down a new stream, so a script bug cannot blast your whole list. We send our newer, still-warming stream through its own transport and limit it in main.cf:
sudo postconf -e \
'smtp-outreach_destination_concurrency_limit = 1' \
'smtp-outreach_destination_rate_delay = 30s'
sudo systemctl reload postfix
That means one connection at a time and 30 seconds between messages to each destination domain. The transport is defined in master.cf:
smtp-outreach unix - - y - - smtp
-o smtp_bind_address=203.0.113.11
-o smtp_helo_name=mail.example.net
Mail is routed to it by sender domain with sender_dependent_default_transport_maps. The full setup is in our Postfix server guide. Daily caps (for example "no more than 50 today") belong in your sending application, since Postfix limits rate, not daily totals.
Warming up when you move off a hosted provider
Moving existing domains from a provider to your own server is a common case, and it is easier than launching a new domain, because the domains already have history. The new IP does not.
In August 2026 we moved three of our own production domains off Mailgun (inbound) and Resend (outbound) onto one self-hosted Postfix server. What made it low-risk:
- The apps kept the old provider as a fallback. Each app relays over authenticated submission (port 587 with SASL). Leaving the SMTP host setting blank sends mail through the old provider again, so rolling back is a config change, not a rebuild.
- Volume stayed low for about two weeks of warm-up. Low volume is when problems are cheapest to notice and fix.
- We verified before moving anything: DKIM key OK, FCrDNS (PTR, forward DNS and HELO agree), blocklists clean, certificate renewal dry-run OK.
If you send more than a few hundred messages a day, split traffic: move one mail type (say, password resets) first, then receipts, then the rest, following the schedule above. If you plan to do the same, our email migration page covers how we approach it for clients.
Warming up a dedicated IP at a provider
The same rules apply if you buy a dedicated IP from a hosted provider instead of running your own server. Some providers offer automatic warm-up, where they gradually shift your traffic from shared IPs to the new one. If yours does not, follow a schedule like the one above, and keep sending at least some mail every day so the IP does not go cold again.
What to watch, and when to slow down
Check these at least daily during warm-up:
# Deferrals and rejections, with the receiver's reason
sudo grep -E 'status=(deferred|bounced)' /var/log/mail.log | tail -n 20
# What is still waiting in the queue
mailq | tail -n 1
Slow down or pause if you see:
- 4xx deferrals mentioning rate limits, unusual traffic or reputation.
- Your own test messages moving from Inbox to Spam.
- A rise in hard bounces (clean the list before continuing).
- Any spam complaints. Gmail wants complaint rates under 0.3%, and you should aim for under 0.1%.
Once you have enough Gmail volume, Google Postmaster Tools shows domain and IP reputation. Until then, test messages to accounts you control at Gmail, Outlook and Yahoo are your best signal.
After warm-up: keeping the reputation you built
Reputation decays and can be lost faster than it was earned. Once you are at normal volume:
- Send consistently. A domain that goes quiet for months is close to cold again. Big, irregular bursts look suspicious.
- Keep lists clean. Remove hard bounces immediately and stop mailing people who never open.
- Introduce new mail types slowly. A first-ever marketing campaign from a domain that has only sent receipts deserves its own small ramp.
- Keep monitoring. Blocklists, DMARC reports, deferrals and complaint rates are a weekly job, not a launch-week job.
Common mistakes
- Treating passing authentication as permission to send volume. Our day-one result shows why.
- Migrating everything at once. When we moved three of our own domains off hosted providers, we kept the old provider configured as a fallback and kept volume low for about two weeks.
- Warming up with a stale list. Old addresses bounce or have become spam traps.
- Trusting naive blocklist checkers. Spamhaus
127.255.255.xanswers mean the query was refused, not that you are listed. UCEPROTECT level 3 lists whole provider networks, not your IP. - Pushing through bad signals. If placement dips, hold at the current level for several days.
- Ramping one domain while another on the same IP misbehaves. IP reputation is shared.
How to verify it worked
Re-check authentication whenever you change anything:
dig +short TXT example.com
dig +short TXT mail._domainkey.example.com
dig +short -x 203.0.113.10
swaks --to check-auth@verifier.port25.com --from hello@example.com \
--server mail.example.com --port 587 --tls \
--auth LOGIN --auth-user hello@example.com
Send a test to mail-tester.com at each step of the schedule, and send identical messages to your own Gmail, Outlook and Yahoo accounts to record Inbox or Spam. Warm-up has worked when those land in the Inbox consistently at your normal volume, with low bounces and no complaints.
If placement stays poor, work through why are my emails going to spam. If you are a bulk sender, check the Gmail bulk sender requirements too. Every server we build under our Server Setup plan comes with a written warm-up plan.