SPF Too Many DNS Lookups: Fixing the 10-Lookup PermError Limit
By VigilDog Team · August 17, 2026 · 6 min read
Your SPF record looked fine for years, then a receiver started returning PermError and messages began landing in spam. The cause is almost always the same: too many DNS lookups. SPF caps the number of DNS queries a record may trigger, and every vendor you add nudges you toward that ceiling. This is a fixable problem once you understand exactly what counts.
Why SPF breaks at 10 DNS lookups
SPF is defined in RFC 7208, and section 4.6.4 sets a hard limit: evaluating a single SPF record may cause no more than 10 DNS-querying mechanisms and modifiers to be resolved. Cross that line and the receiver must return a PermError (permanent error). A PermError is not a soft warning. Most mailbox providers treat it as an SPF failure, which means your carefully aligned DMARC policy can no longer lean on SPF for that message.
The reason for the cap is simple: SPF is evaluated at delivery time, on the receiver's dime. Without a limit, a maliciously nested record could force a receiver to make hundreds of DNS queries per message. Ten was chosen as a generous-but-bounded budget. The catch is that the limit counts nested lookups too, so a record that looks short on the surface can blow past 10 the moment you expand every `include` it points to.
How to count your lookups
Only some mechanisms cost a DNS query. The ones that count toward the limit of 10 are `include`, `a`, `mx`, `ptr`, `exists`, and the `redirect` modifier. The ones that are free are `ip4`, `ip6`, and `all` — these are resolved from the record itself with no extra DNS call. So `v=spf1 ip4:203.0.113.0/24 -all` costs zero lookups, while `v=spf1 include:_spf.google.com include:sendgrid.net include:_spf.salesforce.com -all` costs at least three before you even expand what those includes contain.
That expansion is where teams get caught. `include:_spf.google.com` itself resolves to two or three more includes, each of which is another lookup. There are two secondary limits worth knowing: the `mx` and `ptr` mechanisms may each return at most 10 records, and you are allowed at most two "void" lookups (queries that return no answer) before it also becomes a PermError. The fastest way to see the real total is to run your domain through a validating DMARC and SPF checker that expands every include and prints the running count.
The usual culprits
When a record tips over 10, it is rarely one greedy vendor. It is accumulation. A typical marketing-heavy domain ends up with a stack like this, each line an include that expands into more:
- Google Workspace or Microsoft 365 for corporate mail (often 2-4 lookups on its own)
- A transactional provider like SendGrid, Postmark, or Amazon SES
- A marketing platform such as Mailchimp, HubSpot, or Marketo
- A CRM or support tool that sends on your behalf (Salesforce, Zendesk)
- A leftover include for a vendor you stopped using two years ago
Five ways to get back under the limit
There is no single trick — you combine a few of these until the count is comfortably below 10, ideally with headroom for the next vendor.
First, remove dead includes. Audit every sender and delete any include for a tool you no longer use; this is free and often reclaims two or three lookups instantly. Second, move mail off your root domain onto dedicated sending subdomains — put marketing on `mail.example.com` and transactional on `send.example.com`, each with its own short SPF record, so no single record has to list everyone. Third, replace an `include` with the vendor's published `ip4`/`ip6` ranges when those ranges are stable and documented, since static IPs cost zero lookups. Fourth, drop `ptr` entirely — it is slow, deprecated by RFC 7208, and almost never needed. Fifth, if you genuinely cannot consolidate, consider SPF flattening, but do it with eyes open.
A word on flattening (and staying honest about the risk)
SPF flattening means resolving all your includes down to their raw IP addresses and hard-coding those into a single record, eliminating the nested lookups. It works, and it can take a record from 14 lookups to zero. But it trades one problem for another: when a vendor changes their sending IPs — and they do, without telling you — your flattened record is now wrong and mail silently fails SPF until someone notices. If you flatten, you are signing up to keep those IPs in sync, either manually on a schedule or with tooling that re-flattens and re-checks automatically.
That maintenance burden is exactly why SPF is worth monitoring rather than setting and forgetting. A record that is valid today can drift over the 10-lookup line the next time someone adds a webinar tool, and a flattened record can go stale the next time a provider rotates IPs. Continuous checks on SPF, DKIM, and DMARC — the kind built into VigilDog's monitoring — catch a PermError the day it appears instead of the week your open rates crater. If you want the manual version first, our guide to fixing SPF, DKIM, and DMARC walks the whole record set end to end.
