SPF PermError: too many DNS lookups, and how to get back under 10
Your mail was authenticating fine, you added one more vendor to your SPF record, and now reports show PermError and some receivers are failing your mail outright. You did not break the syntax. You crossed a hard limit that has been in the SPF specification from the start: a single SPF evaluation may trigger at most 10 DNS lookups. The eleventh is not a warning. It is a permanent error, and a record in PermError authenticates nothing.
What counts as a lookup
This is where people miscount. Each of these mechanisms costs one DNS lookup when SPF is evaluated:
include:— one lookup, plus every lookup inside the included record, recursively.aandmx— one lookup each (andmxthen resolves each host).ptr— one lookup (and it is deprecated; avoid it).exists:— one lookup.
What does not count: ip4:, ip6:, and all. Those are evaluated directly with no DNS query.
The trap is recursion. include:_spf.google.com looks like one lookup, but that record itself contains more includes, and those expand further. A single popular provider include can quietly consume three or four of your ten. Stack a mail platform, a CRM, a helpdesk, and a marketing tool, and you are over the limit without a long-looking record.
Count yours first
Do not guess. Expand the record fully and count the real total. The SPF generator parses a record, expands every nested include, and shows the running lookup count so you can see exactly which mechanism pushed you past 10. Frequently it is one heavyweight include doing most of the damage.
How to get back under the limit
Remove what you no longer send from. The cheapest fix is deleting includes for vendors you stopped using. Old include: entries linger for years. Each one you remove frees its entire recursive subtree.
Prefer DKIM over SPF for third parties. DMARC needs only one of SPF or DKIM to align. If a vendor supports DKIM signing with your domain, you can often drop their SPF include entirely and rely on DKIM, which costs zero SPF lookups and survives forwarding. This is the most durable way to reclaim budget.
Flatten the heavy includes to IP ranges. Replace an include: with the ip4:/ip6: ranges it resolves to. Those cost no lookups. The cost is maintenance: if the provider changes their sending IPs, your flattened record goes stale and starts failing. Only flatten providers with stable, published ranges, and document that you have done so.
Consolidate subdomains. Sending different streams (transactional, marketing, support) from dedicated subdomains gives each its own SPF record with its own budget of 10, instead of cramming every source into the root domain.
Use a single delegated include if your provider offers one. Some SPF-management services give you one include: that they keep flattened and updated on their side, turning many lookups into one.
Verify the fix
After editing, re-expand the record and confirm the total lookup count is 10 or fewer with margin to spare — leave room for the next vendor you add. Then check that it still covers every legitimate source by reading your DMARC aggregate reports in the DMARC report viewer; a source you accidentally dropped while trimming will show up there as a new alignment failure.
Re-run your record through the SPF generator to count the lookups and confirm yours is back under the limit.