SPF: too many DNS lookups (PermError)
SPF has a hard budget: ten DNS-querying terms per evaluation — the include, a, mx, ptr and exists mechanisms plus the redirect modifier, counted once each. It exists so that one crafted message cannot make a receiver perform hundreds of lookups on the sender's behalf. Cross it and the result is an SPF PermError — and most receivers treat PermError as no usable SPF at all.
When the SPF lookup limit is exceeded there is no warning anywhere — that is what makes this failure nasty. Nothing warns you. The record still looks reasonable in a text editor. It simply stops authorising anything, everywhere, from the moment the eleventh lookup appears — usually the day somebody added one more include: for a new newsletter tool.
What counts, and what does not
| Counts against the limit | Free |
|---|---|
include | ip4 |
a | ip6 |
mx | all |
ptr (deprecated — remove it) | exp |
exists | |
redirect |
Two details decide most real cases:
- Too many includes is the usual cause, and
includeis recursive.include:_spf.google.comcosts one lookup for itself plus every lookup inside that record. A single include can quietly consume four or five of your ten. mxcounts once, but is not free. It costs one term like any other, and separately RFC 7208 caps the address lookups a singlemxmay trigger at ten. A domain with a dozen MX hosts hits that sub-limit rather than the main one.
The limit is on the evaluation, not on your record. You can be at nine today and at eleven tomorrow because a provider added an include to their record — without touching yours. The syntax reference is in SPF record syntax.
How to count yours
Any SPF checker will report the total, and our own free DMARC and SPF tools do it against live DNS. Counting by hand is only realistic for flat records, because you have to expand every include recursively and re-expand it whenever a provider changes.
The SPF 10 lookup limit is a ceiling, not a target: treat eight as your working limit. The two you leave spare are what absorbs a provider expanding their own record.
The four ways back under the limit
1. Remove senders you no longer use
Too many includes is the usual shape of the problem, so this is almost always the biggest win — and the only one with no downside. Records accumulate: a CRM from two vendors ago, a survey tool used once, a helpdesk that was replaced. Each is an include nobody has audited.
The reports tell you which of them still send. A source that has produced no mail in ninety days is a candidate for removal — Sending sources, grouped by provider is the fastest way to see it.
Check reports before deleting, not after. An include with low volume may be your invoicing system, which sends thirty messages a month and matters enormously.
2. Replace an include with the addresses it resolves to
If a sender publishes a small, stable set of IPs, ip4: entries cost nothing:
include:mail.vendor.example → ip4:198.51.100.0/28
The trade is explicit: you take on the maintenance. When the vendor changes IPs, your mail fails, and nobody tells you. Do this only for senders that document a fixed range and commit to it.
3. Use subdomains for bulk senders
The cleanest structural fix. Send marketing from news.example.com and transactional from mail.example.com, each with its own SPF record and its own budget of ten.
This is better than a workaround. It separates reputations — a bad marketing week stops affecting invoice delivery — and it makes each record small enough to read. DMARC still covers the subdomains through your organisational policy.
4. SPF flattening — understand the cost first
SPF flattening means resolving every include down to raw ip4/ip6 entries, usually with a tool that regenerates the record on a schedule.
It works, and it moves a silent failure mode to a different place. Your record now hardcodes infrastructure you do not control. When Google or Microsoft changes an IP range, your SPF is wrong until the next regeneration — and if the automation stops running, nothing alerts you. If you flatten, it must be automated and monitored; a one-time manual flatten is a slow-motion outage.
Why this matters less than it used to
A domain with aligned DKIM on every sender does not lose mail when SPF returns PermError, because DMARC passes on either aligned check. SPF failing is then a problem to fix rather than an emergency.
That is one more reason to get DKIM right on every platform before touching the SPF record, and it is the same reason forwarded mail survives: SPF, DKIM and DMARC — how they fit together.
After you change the record
Publish, wait for DNS TTL, then verify from the outside rather than from the control panel. PermError is a property of the whole evaluation, so a record that passes a syntax check can still bust the limit through an include. Watch the next few days of reports for SPF results returning to pass on the senders you kept: How to read a DMARC report.