SPF flattening explained
SPF flattening rewrites your SPF record so it authorizes the same senders without triggering DNS lookups — the fix for a record that has grown past the 10-lookup limit.
How SPF flattening works
A normal SPF record delegates to other senders with include mechanisms:
v=spf1 include:spf.protection.outlook.com include:_spf.salesforce.com ~all
Each include is a DNS lookup, and those includes contain nested includes that
cost more lookups. Flattening resolves that entire tree down to the leaf IP ranges and
lists them directly:
v=spf1 ip4:40.92.0.0/15 ip4:40.107.0.0/16 ip4:52.100.0.0/14
ip4:13.110.208.0/21 ip4:136.146.0.0/15 ... ~all
Because ip4: and ip6: don’t count toward the limit, the
flattened record can hold every authorized IP in zero lookups.
SPF is validated by counting DNS-lookup-causing mechanisms. Per RFC 7208 §4.6.4, evaluating a record may trigger at most 10 of these:
includeamxptr(deprecated — avoid)existsredirect
ip4:, ip6:, all, and exp do
not count. Crucially, each include can contain its own nested
includes, and every lookup in that tree counts — so a handful of legitimate
providers compounds past 10 fast. There is also a separate limit of 2 “void”
lookups (mechanisms that resolve to nothing); exceeding either produces a
permerror.
A worked example
Here is a realistic record for a business running Microsoft 365 plus a CRM and a couple of legacy hosts:
v=spf1 include:spf.protection.outlook.com include:_spf.salesforce.com
include:secureserver.net include:sendgrid.net include:mail.example.com ~all
Counting recursively, the includes above can expand well past 10 DNS lookups — even though every sender is legitimate. The domain owner can’t shrink the nested provider records (those belong to Microsoft, Salesforce, and so on), and those providers change their IPs whenever they need to. That is exactly the situation flattening and macros are designed to solve.
How to flatten an SPF record (manually)
- Inventory your senders. List every service that sends mail as your domain — mailbox provider, CRM, marketing tool, help desk, invoicing app.
- Resolve each include to its
ip4:/ip6:ranges recursively (an SPF flattening tool does this for you). - De-duplicate overlapping ranges.
- Rebuild one record with the IPs and a single
~allor-all. Mind the 255-character string limit. - Publish and verify that your lookup count is under 10 and the record still passes for your real senders.
The catch: static records go stale
A hand-flattened record is a snapshot of your providers’ IPs at one moment. When Microsoft, Google, or your CRM changes its sending ranges, your record is now wrong and mail from the new IPs fails SPF — silently. That is why flattening is only half the solution.
Self-healing flattening
A managed service solves the staleness problem: you delegate the flattening to a hosted record
(via a single include or a macro), and it is
re-resolved automatically whenever an upstream provider changes. You keep the single-lookup
result permanently, without babysitting IP lists. Compare approaches on our
SPF flattening tools page.
Why this matters for DMARC
A permerror means SPF didn’t return a clean pass. Under
DMARC, that removes SPF as a passing authentication method, so
alignment now rests on DKIM alone. If DKIM also fails or isn’t aligned, a
p=quarantine or p=reject policy will send legitimate mail to spam or
bounce it outright. Keeping SPF under the limit is a prerequisite for enforcing DMARC safely.
Frequently asked questions
How do I flatten my SPF record?
include/a/mx mechanism to its IP ranges, de-duplicate them, and publish a single record listing those ip4:/ip6: values with one ~all or -all. A flattening tool automates the resolution.