Email deliverability Q&A

What is SPF flattening?

Samuel Chenard

By Samuel Chenard · CEO & Co-Founder, Palisade · Reviewed July 20, 2026

SPF flattening replaces the include: mechanisms in your SPF record with the IP addresses they resolve to, so evaluation stays under the 10-DNS-lookup limit in RFC 7208. The trade: providers rotate their sending ranges, flattened IPs go stale, and legitimate mail starts failing SPF. Treat it as a last resort with a maintenance schedule attached.

At a glance
What it isReplacing include: mechanisms with the ip4:/ip6: addresses they currently resolve to
Why it existsRFC 7208 section 4.6.4 caps DNS-querying terms at 10 per SPF evaluation
Over the limitThe check returns permerror, and DMARC treats that as an SPF failure
The riskProviders rotate sending IPs; a flattened record goes stale with no warning
Microsoft's positionDo not flatten include:spf.protection.outlook.com; its IPs change frequently
AlternativesPrune dead mechanisms, segment senders onto subdomains, macro-based SPF, hosted SPF

SPF records delegate trust through include: mechanisms: include:_spf.google.com means "whatever IPs Google lists are allowed to send as my domain." Every include costs a DNS query at check time, and RFC 7208 puts a hard cap on those queries. Section 4.6.4 states: "SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS." Exceed it and the RFC is equally blunt: "If this limit is exceeded, the implementation MUST return 'permerror'." The full mechanics live in the glossary entry for the SPF lookup limit at /learning/glossary/spf-lookup-limit; this page is about the workaround everyone reaches for.

Flattening is that workaround. You resolve each include: down to the raw addresses behind it, publish those as ip4: and ip6: terms, and delete the include. Since IP terms cost zero lookups, a record that blew past the limit at 14 lookups can flatten to one that needs none. Your mail passes SPF again, and every checker goes green.

The catch is that an include is a live pointer and a flattened IP list is a snapshot. The provider keeps updating what sits behind their include; your snapshot does not update itself. Flattening trades a visible, immediate problem (permerror today) for an invisible, deferred one (valid mail failing SPF whenever a provider shuffles ranges). That trade can still be worth making, but only deliberately, and only for the right senders.

Triage flow for an SPF record over the 10-lookup limit: count what each term costs, prune dead includes, segment senders onto subdomains, and flatten only as a last resort with scheduled re-resolution or a hosted SPF service.

What counts against the 10-lookup limit (RFC 7208, section 4.6.4)

SPF termCosts a DNS lookup?Why
include:Yes, plus every lookup inside the included recordFetches and evaluates another domain's SPF record; nesting compounds
aYesResolves a hostname's A/AAAA records at check time
mxYes, plus one per MX host returnedResolves the MX set, then each MX host's addresses
ptrYes (and the RFC says do not use it)Reverse-DNS lookup on the connecting IP; slow and deprecated
exists:YesAn A lookup on a constructed name, usually macro-driven
redirect=YesHands evaluation to another record, lookups included
ip4: / ip6:NoLiteral addresses; nothing to resolve. This is why flattening works.
all / exp=NoNo query at evaluation time (exp only fires after a fail)

The RFC's own wording, verbatim: "The following terms cause DNS queries: the 'include', 'a', 'mx', 'ptr', and 'exists' mechanisms, and the 'redirect' modifier." And: "The other terms -- the 'all', 'ip4', and 'ip6' mechanisms, and the 'exp' modifier -- do not cause DNS queries at the time of SPF evaluation, and they are not subject to this limit." Checked 2026-07-20; link in Sources.

What flattening actually does

Take a record that authorizes Microsoft 365, a marketing platform, a helpdesk, and a billing tool through four includes. Each include costs at least one lookup, and includes nest: a vendor's include often contains further includes, and every layer counts against your 10. Fewer than ten include: statements in your record does not guarantee fewer than ten lookups. The glossary entry at /learning/glossary/spf-include covers the nesting mechanics.

A flattening pass resolves that whole tree. include:spf.protection.outlook.com currently expands to six ip4: ranges and five ip6: ranges (checked 2026-07-20 via live DNS); the marketing platform expands to a dozen more. You publish the union as literal IP terms and your lookup count drops to zero. The record gets long (often past the 255-character single-string limit, so it gets split into multiple quoted strings) but it evaluates instantly.

Note what did not change: the set of servers allowed to send as your domain is identical the moment you flatten. Flattening is not a security change. It is a caching decision, and like all caches, the interesting question is what happens on invalidation.

The risks: stale IPs and silent failure

Providers treat their include as the contract and everything behind it as an implementation detail they can change without notice. Microsoft is explicit about its own service in its SPF documentation: do not flatten include:spf.protection.outlook.com, because "Microsoft's sending infrastructure uses dynamic IP addresses that change frequently." The same page allows flattening only for vendors with "stable, documented IP address ranges" and tells you to "review and update the flattened entries at least quarterly." That is the vendor selling you the mail service telling you the workaround needs a recurring calendar entry.

The failure mode is nasty because it is quiet. When a provider adds a range your snapshot lacks, mail from the new IPs fails SPF while mail from the old IPs keeps passing, so delivery degrades partially and intermittently instead of all at once. Nobody gets paged. The evidence shows up in DMARC aggregate reports as authorized senders failing SPF, and, once receivers enforce, as bounced campaigns. If you are at p=reject with no DKIM backstop for that sender, a stale flattened record turns provider maintenance into your outage.

The other cost is ownership. An include meant the provider maintained the record; a flattened record means you do, for every vendor, forever. Multiply that by each domain you run and flattening quietly becomes a standing operational chore with an SLA nobody agreed to.

Alternatives that age better

Prune before you flatten. Most over-limit records carry dead weight: includes for tools the company dropped two years ago, an mx mechanism for a host that no longer sends, a stray ptr. Deleting a defunct include recovers its whole nested lookup cost and removes an authorized sender you no longer trust. Plenty of records get back under 10 on pruning alone.

Segment senders onto subdomains. Point marketing at marketing.example.com and billing at billing.example.com, each with its own SPF record. Every subdomain gets its own 10-lookup budget, and Microsoft's documentation recommends the split for an independent reason: a bulk sender's reputation problem stops bleeding into the domain your employees mail from.

Macro-based (dynamic) SPF. A single exists: mechanism with a macro, like exists:%{i}.spf.example.com, turns each check into one per-IP DNS query against a zone you control, replacing any number of includes with one counted lookup. It is the most elegant answer and the easiest to get wrong, since your DNS zone becomes the authorization engine. See the glossary entry at /learning/glossary/spf-exists for the pattern.

Hosted SPF. A managed service publishes and continuously re-resolves your record, so provider IP rotations propagate without you touching DNS. This is flattening with the maintenance burden moved to software that actually runs on a schedule, and it is the practical choice once the record protects revenue mail. Palisade hosts SPF records this way, alongside hosted DKIM, DMARC, and MTA-STS, with a 100% DNS uptime guarantee.

SPF lookup-limit triage

SymptomLikely causeThe fix
Checker reports more than 10 lookupsInclude nesting: vendors' records pull in further includesPrune dead senders first, then segment subdomains before flattening
permerror in DMARC reports or checkersOver the lookup limit, or an include pointing at a dead domainCount lookups, remove or repair the offending mechanism
Valid mail failing SPF weeks after you flattenedProvider rotated ranges; your snapshot is staleRe-resolve every flattened include; restore the include for dynamic providers
Record rejected or truncated by your DNS hostFlattened record exceeds 255 characters in one stringSplit into multiple quoted strings, or cut the record back down
One provider's mail failing, others fineThat provider's new IPs are missing from the flattened listCheck their published ranges against your record, update, and calendar the review

permerror is the SPF result name, not a bounce code; receivers translate it into their own rejections. The glossary entry at /learning/glossary/spf-permerror covers how each DMARC receiver treats it, and the walkthrough at /learning/how-do-i-fix-spf-permerror-too-many-dns-lookups goes mechanism by mechanism.

Triage flow for an SPF record over the 10-lookup limit: count what each term costs, prune dead includes, segment senders onto subdomains, and flatten only as a last resort with scheduled re-resolution or a hosted SPF service.

How to fix it

  1. Count your lookups before touching anything

    Run your domain through the free SPF checker below. It resolves the full include tree and shows the real lookup count, which is routinely higher than the number of includes you can see in the record.

    Run the check now

    Enter your sending domain and the check runs instantly on the next page. Free, no signup.

  2. Prune dead mechanisms

    Match every include against the tools you actually pay for. Defunct services, duplicate includes, and any ptr mechanism go first; each deletion recovers its whole nested lookup cost and shrinks your attack surface at the same time.

  3. Move bulk senders onto subdomains

    Give marketing and other high-volume tools their own subdomain with its own SPF record and its own 10-lookup budget. This also keeps a campaign tool's reputation trouble away from your primary domain.

  4. Flatten only stable ranges, and calendar the review

    If you still need headroom, flatten only vendors that publish stable, documented ranges, never dynamic clouds like Microsoft 365. Record what you replaced and re-verify at least quarterly, which is Microsoft's own documented interval.

  5. Or move the record to a host that re-resolves it

    Hosted SPF keeps the record current automatically as providers rotate ranges, which is the durable version of flattening. Then confirm alignment end to end, since a passing SPF record only helps DMARC when the domains align.

Related free tools: SPF record generator · DMARC checker · Email security score

The lookup limit is a detour; enforcement is the destination

Nobody flattens SPF for fun. You are fixing lookups because SPF has to pass, aligned, for DMARC to move to enforcement without dropping your own mail. A record that validates today but decays as providers rotate ranges is exactly the kind of landmine that stalls domains at p=none forever, or worse, detonates after you reach p=reject.

Palisade's agent hosts the SPF record, keeps it current as providers change ranges, reads the DMARC aggregate reports to confirm every legitimate sender authenticates, and executes the move to p=reject when the data says it is safe. Monitoring tells you the record broke; enforcement with a maintained record is the point.

DMARC software that does the work

Palisade's AI agent hosts your SPF, DKIM, and DMARC records and takes every domain to p=reject automatically. Your first domain is free.

First domain free forever

Why it matters for MSPs

Flattening is barely defensible on one domain and indefensible on two hundred. Every tenant that stacks Microsoft 365 plus a PSA-linked mail tool plus a marketing platform is flirting with the limit, and hand-flattened records across a client book means every provider IP rotation becomes a fleet-wide stale-record hunt. Standardize instead: prune at onboarding, segment bulk senders onto subdomains as policy, and put client records on hosted SPF so rotations propagate without a ticket. Palisade hosts SPF, DKIM, and DMARC records per client domain at $9/domain/mo (dropping to $7 at 100+ domains and $5 at 1,000+), walks each domain to p=reject, and files the alerts through native ConnectWise, HaloPSA, and Autotask integrations. Your own MSP domain is a free NFR domain to test the pattern on.

Frequently asked questions

As a last resort, with conditions. Prune dead includes and segment senders onto subdomains first; those fixes do not decay. Flatten only vendors with stable, documented ranges, never dynamic clouds like Microsoft 365, and re-verify the IPs at least quarterly. Unmaintained flattening is a deferred outage, not a fix.

Ten per evaluation. RFC 7208 section 4.6.4 requires implementations to limit DNS-querying terms (include, a, mx, ptr, exists, and the redirect modifier) to 10, and to return permerror beyond that. Nested includes count too, so a record with four visible includes can easily spend twelve lookups.

The check returns permerror, a permanent evaluation error. DMARC treats permerror as an SPF failure, so mail from that domain loses SPF entirely and rides on DKIM alone; if DKIM is missing or unaligned for a sender, receivers enforcing your DMARC policy will quarantine or reject legitimate mail.

No. Microsoft's own documentation says not to flatten include:spf.protection.outlook.com because its sending infrastructure uses dynamic IP addresses that change frequently. Keep the include, then recover lookups elsewhere: prune dead mechanisms, move bulk senders to subdomains, or flatten a vendor whose ranges are actually stable and documented.

Microsoft's guidance says review and update flattened entries at least quarterly, and that is a floor, not a target. Providers do not announce range changes to you, so the honest options are automated re-resolution (hosted SPF) or a recurring audit you actually run. A flattened record with no owner is already broken; you just have not noticed yet.

A pattern that replaces stacked includes with one exists: mechanism plus a macro, like exists:%{i}.spf.example.com. Each check becomes a single per-IP query against a DNS zone you control, so one counted lookup covers any number of senders. It scales well but demands real DNS discipline, since that zone becomes your authorization engine.

Only through freshness. A correctly flattened record passes SPF exactly like the includes it replaced, so DMARC alignment is unchanged on day one. The risk arrives later: stale IPs turn authorized senders into SPF failures, and under an enforced DMARC policy those failures become quarantined or rejected mail unless aligned DKIM still covers the sender.

Sources

Every benchmark above was verified against the vendor's own documentation on the date shown.

Related reading

Email deliverability, fixed: the full guide