Of the Tranco top-1M domains, 623,370 publish an SPF record as of the 2026-07-05 snapshot of our daily email infrastructure report. Every one of those records is subject to a constraint written into RFC 7208 that predates the modern multi-vendor sending stack: a receiving server evaluating SPF may perform at most ten DNS lookups. The eleventh does not degrade gracefully. It terminates evaluation with PermError— and from the receiver's point of view, your mail is now unauthenticated.
What counts against the ten
The limit is about DNS queries triggered by mechanisms, not about the length of the record. The accounting works like this:
| Term | Lookup cost | Notes |
|---|---|---|
include: | 1 + everything inside | The dominant budget consumer; nested includes count recursively |
redirect= | 1 + everything inside | Same recursion as include |
a / a:domain | 1 | Resolves an address record |
mx / mx:domain | 1 (plus target resolution) | MX lookup, then address lookups for its targets |
exists: | 1 | Rare outside anti-spam macros |
ptr | 1 | Deprecated by RFC 7208 — spend the byte deleting it, not the lookup running it |
ip4: / ip6: / all | 0 | Literal data, free at evaluation time |
The recursion is what catches people. When you write include:spf.example-esp.com, you are not spending one lookup — you are spending one plus whatever that vendor nests inside. Vendors restructure their SPF trees without asking you. A record that evaluated at eight lookups when you deployed it can cross eleven a year later with no change on your side, which is why lookup exhaustion so often looks like a spontaneous deliverability incident.
How the budget disappears in practice
The pattern we see across the top million is structural, not careless. Section 6 of the live report covers SPF mechanics across the dataset, and the ESP analysis shows the underlying cause: multi-ESP sending is now the norm — the per-provider shares in our data sum to well over 100% of SPF domains because a typical company runs one vendor for marketing, another for transactional, a helpdesk that sends as the domain, plus the mailbox provider itself. Each of those is an include. A completely reasonable stack — mailbox provider, CRM, helpdesk, marketing platform, billing system — can sit at or past the limit before anyone has done anything wrong. We look at what healthy versions of these stacks look like in our multi-ESP analysis.
A typical over-budget record looks unremarkable:
v=spf1 include:_spf.google.com include:spf.protection.outlook.com
include:mail.zendesk.com include:_spf.salesforce.com
include:servers.mcsv.net include:amazonses.com
a mx ~allCount the visible terms and you get eight. Count after recursion and you are likely past ten — several of those vendor includes fan out into two or three nested lookups of their own. Nothing in the record's syntax warns you; only full recursive evaluation does.
What PermError does to your mail
PermError is worse than a soft failure, because it is both silent and interpreted harshly:
- SPF stops contributing to authentication. The receiver could not evaluate your policy, so your legitimate mail gets no SPF pass — at every receiver, on every message, until the record is fixed.
- DMARC counts it against you. A PermError on SPF means SPF cannot produce an aligned pass. If DKIM alignment also fails on a given message — a forwarded message, a vendor signing with its own domain — that message now fails DMARC outright.
- Nobody tells you. There is no bounce for a PermError on an otherwise deliverable message. The evidence accumulates quietly in DMARC aggregate reports, which is one more reason a monitored
rua=address is not optional.
Lookups are not the only ceiling. Once a record and its DNS envelope push past roughly 450 bytes, you risk UDP fragmentation and truncated responses — some resolvers will simply fail to retrieve the record. Long chains of includes and long ip4 lists both walk toward this cliff from different directions.
Auditing and trimming your record
The audit is mechanical: recursively resolve every include and redirect in your record and count. Any competent SPF checker automates this; you can also do it by hand with dig txt in about five minutes for a typical record. When the count is at nine or above, trim in this order:
- Delete the archaeology. Includes for vendors you left years ago are the cheapest wins. Our dataset shows decommissioned-ESP includes surviving for years — senders rarely clean up.
- Drop
ptrand questiona/mx. ptr is deprecated outright. The a and mx mechanisms usually duplicate hosts already covered by an include, and mx spends extra resolution on targets that often do not send at all. - Move bulk senders to subdomains. Marketing mail from
news.example.comwith its own SPF record gets its own ten-lookup budget and isolates reputation as a bonus. - Flatten as a last resort — with automation. Replacing includes with their resolved ip4 blocks eliminates lookups, but vendor IPs change without notice; hand-flattened records rot into false failures. Flattening also has a side effect on measurement studies like ours: flattened records are invisible to DNS surveys.
One final check while you are in the record: make sure the qualifier on all is doing what you think. The lookup limit breaks SPF by accident; a bad qualifier breaks it on purpose — see our tour of +all records for the failure mode at the other extreme.