DMARC
The SPF Redirect Trap: Why Flattening Fixes PermError Today and Breaks Mail Flow Later
October 6, 2026
Rodney Hall, COO— AI-assisted and reviewed prior to publication.

Every MSP that has inherited a client's email stack has run into the same wall: an SPF record that worked fine for years suddenly starts failing, and the cause traces back to a limit almost nobody reads about until it bites them. The instinct is to flatten the record, resolve every include down to raw IP addresses, and declare victory. That fix works right up until a vendor renumbers its sending infrastructure and the client's legitimate mail starts bouncing with no warning at all.
Why Does SPF Cap Out at 10 DNS Lookups?
SPF evaluation is capped at 10 DNS mechanism lookups per check because the protocol's authors needed to stop a malicious or misconfigured record from forcing unbounded recursive queries onto every receiving mail server on the internet. The limit comes directly from the specification: RFC 7208 requires that SPF implementations must not perform more than 10 DNS lookups during evaluation, counting every include, a, mx, exists, and redirect mechanism, including everything nested inside them. Cross that line and the receiver does not keep counting or fail open. It stops, returns a PermError, and treats the entire message as having failed SPF, no matter how legitimate the sending source actually was.
That design choice is reasonable DNS hygiene. It is also a trap for any domain running more than three or four mail-sending services, which describes most small and mid-sized businesses an MSP supports. Google Workspace alone recommends publishing include:_spf.google.com and then layering in every other sender as its own mechanism, and its own documentation is explicit that a domain's SPF record must list every service authorized to send on its behalf or legitimate mail risks being rejected or routed to spam, as Google's admin guidance lays out. Add a helpdesk tool, a CRM, an invoicing platform, and a marketing sender, each with its own nested include chain, and a client can quietly cross 10 lookups without anyone touching the DNS record directly.
The Flattening Fix and What It Actually Trades Away
SPF flattening replaces every include mechanism with the literal IP ranges it resolves to, which collapses a record that might need a dozen lookups down to one or two. It is a legitimate, standards-compliant way to solve a PermError, and plenty of MSPs reach for it as the default answer whenever a client's record creeps past the limit. The problem is not the technique. The problem is what it quietly removes from the equation: a live pointer to the vendor's current sending infrastructure.
When a record uses include:sendgrid.net or include:_spf.google.com, the receiving server resolves that include at evaluation time and always gets the vendor's current IP ranges. A flattened record freezes those ranges as a snapshot the moment it was generated. As one flattening provider's own FAQ puts it, flattening itself is standards-compliant, but the real risk is staleness, since a static flattened record breaks silently the moment a provider changes its IPs, which is exactly why a self-healing or managed approach is positioned as the safer path by that vendor's own documentation on the tradeoffs of static flattening.
That staleness problem compounds with a second, less-discussed constraint. A flattened record that lists many IP ranges can bump into DNS's own size limits: a single character string in a TXT record cannot exceed 255 octets, and the specification itself advises keeping the full response under 450 octets so it still fits in a single UDP packet, a detail documented in the practical walkthrough on SPF flattening risks. An MSP that flattens aggressively to solve a lookup problem can end up creating a length problem instead, one that is just as capable of producing a PermError.
How a Legitimate Sender Change Turns Into a Months-Later Outage
A flattened record goes stale the same way it gets built: silently. A vendor migrates data centers, adds a region, or retires an old IP block, typically with a changelog nobody at the MSP or the client is subscribed to. The flattened SPF record keeps publishing the old addresses because nothing in DNS forces it to update, and mail from the vendor's new IPs simply stops matching any mechanism in the record.
Nobody notices immediately because most sending volume still comes from IPs that haven't changed yet. The failures show up as a slow trickle, a support ticket here, a missed invoice there, often two or three months after the vendor's migration, long after anyone would think to connect the symptom back to a DNS record that was "fixed" in the past. This is precisely the kind of drift that a named mail provider's own guidance on reading authentication reports describes: regular review of DMARC aggregate data catches infrastructure drift early, including an SPF record that has grown stale as vendors change their sending IPs, according to Zoho's guidance on DMARC reports. Without that review habit, a flattened record can be wrong for a long time before anyone reads the symptom correctly.
For MSPs managing dozens of client domains, this is where flattening becomes an operational liability rather than a one-time fix. A typical mid-market client already running seven or more SaaS tools sits close to the lookup threshold before any flattening happens at all, meaning a single new service addition can trigger a PermError without warning, a pattern documented in an MSP-focused technical guide to the 10-lookup limit. Flatten that record once and the MSP has traded a visible, periodic lookup-count problem for an invisible, open-ended staleness problem that depends entirely on someone remembering to re-flatten after every vendor change.
What Breaks When a Flattened Record Goes Stale
The table below compares what an MSP is actually trading when choosing between a conventional include-based record and a flattened one.
| Factor | Include-based record | Flattened record |
|---|---|---|
| Lookup count | Can exceed 10 as vendors are added | Reduced to 1-2 regardless of vendor count |
| Vendor IP changes | Resolved automatically at evaluation time | Frozen at the moment of flattening |
| Failure mode | PermError if lookups exceed 10 | Silent SPF fail once IPs drift, no error raised |
| Maintenance burden | Monitor lookup count as vendors are added or removed | Re-flatten every time any included vendor changes IPs |
| Record size risk | Low, since includes stay short | Can approach the 255-octet string and ~450-octet response limits |
Is Flattening Ever the Right Call?
Flattening is defensible when a domain genuinely cannot reduce its sender count below the limit and the MSP has a reliable way to detect vendor IP changes before they cause failures. It is a poor default when the underlying problem is really an SPF record nobody has pruned, since outdated or unnecessary vendor entries are a common reason domains hit the limit in the first place rather than a genuine need for flattening, a point made plainly in PowerDMARC's own flattening tool documentation. The first move on any client record that is pushing 10 lookups should be an audit of what is actually still sending mail, not an automatic flatten.
Where flattening is unavoidable, it has to be paired with continuous monitoring rather than treated as a one-time DNS edit. That means watching DMARC aggregate reports for new or disappearing source IPs, not just checking the record once at deployment and moving on. For MSPs setting this up across a client base for the first time, the getting-started guide walks through how to pair SPF record changes with DMARC reporting so vendor drift shows up as a flagged event instead of a support ticket three months later.
Building Visibility Back Into SPF Operations
The actual fix for the flattening trap is not choosing between flattening and includes. It is refusing to let either choice become invisible. A record built on includes needs its lookup count tracked every time a vendor is added or removed. A flattened record needs its underlying IP ranges checked against each vendor's current published ranges on a recurring schedule, not whenever someone happens to remember.
This is where most MSPs discover that spreadsheet tracking does not scale past a handful of clients. Automated scanning that re-evaluates every client domain's SPF record on a schedule, flags lookup counts approaching the limit, and diffs flattened IP ranges against vendor changes turns a silent failure mode into a dashboard alert. ActiScan's domain scanning is built around exactly that recurring check, and MSPs comparing plans can see how it fits alongside DMARC and DKIM monitoring on the pricing page.
A few habits separate MSPs who catch this early from the ones who find out from an angry client:
- Review every client's SPF lookup count whenever a new sender is onboarded, not just when a PermError appears.
- Treat a flattened record as a maintenance commitment with an owner and a recheck cadence, not a permanent fix.
- Feed DMARC aggregate reports into a regular review so a vendor's silent IP migration shows up as a new failing source instead of a mystery.
None of this requires exotic tooling, just a process that runs on a schedule instead of a memory. MSPs who want that process running across a client book rather than tracked domain by domain can get a baseline scan started from the sign-up page in less time than it takes to manually recount one client's SPF lookups.
The SPF redirect and flattening trap is not really a DNS problem. It is a visibility problem wearing a DNS costume. The 10-lookup limit will keep doing exactly what RFC 7208 designed it to do, and vendors will keep changing their sending infrastructure without asking permission. The only durable answer is making sure someone, or something, is watching both at once.