The SPF 10 DNS lookup limit, explained
Evaluating an SPF record may cost at most ten DNS lookups. RFC 7208 sets this cap to stop SPF being used to amplify DNS traffic. Exceed it and the check returns permerror, which most receivers treat as a failure — so adding one sending service too many can break authentication for every message you send.
Which mechanisms count
Not everything in a record costs a lookup. The ones that do are include, a,
mx, ptr and exists, plus the redirect modifier.
Each counts once when it is evaluated.
The ones that do not are ip4, ip6 and all. An address
hard-coded into the record needs no resolution, which is why flattening an include into explicit IP
addresses reduces the count — and why it is the standard escape hatch when you run out of room.
The part that catches people out
The ten applies to the whole evaluation, not to your record alone. Every include pulls in another record, and that record's own includes count against your total.
A record reading v=spf1 include:_spf.google.com include:sendgrid.net ~all looks like
two lookups. It is not. Google's record contains further includes of its own, and so does
SendGrid's. Two visible mechanisms can easily resolve to eight or nine real lookups. This is why a
record that worked fine for a year breaks the day someone adds a helpdesk tool: the new include was
not the tenth, it was the eleventh.
Providers also change their own records without telling you. A record that sat at nine lookups can cross the limit because an upstream provider restructured, with no change on your side at all. Nothing warns you — authentication simply starts failing.
What happens when you exceed it
The check returns permerror, a permanent error. It does not fail softly, and it does
not fall back to evaluating the first ten mechanisms. The entire record is treated as invalid.
How that lands depends on the receiver. Many treat permerror as equivalent to a fail. If you also publish DMARC with a policy of quarantine or reject, and DKIM is not aligned for that message, the mail is quarantined or rejected. A single include too many can therefore take down delivery for a domain whose records all looked correct.
Staying under the cap
Remove what you no longer use. Most records accumulate includes for services that were trialled and abandoned; every one still costs a lookup. Audit the list against what you actually send with.
Replace a and mx mechanisms with explicit ip4 entries where
your sending IPs are stable. Both cost a lookup and neither is necessary if you know the addresses.
Avoid ptr entirely — it is deprecated and slow.
Where you genuinely need many senders, consider flattening: resolve a provider's include to its IP ranges and publish those directly. It works, but it is maintenance you now own, because those ranges change without notice. Flattening without monitoring trades a hard failure today for a silent one later. A subdomain for bulk sending is often the better answer — it gets its own SPF record and its own budget of ten.
One record, not two
Worth stating alongside the lookup limit, because it causes the same symptom: a domain may publish
exactly one SPF record. Two TXT records both beginning v=spf1 is a permanent error, and
the check fails outright. Merge the mechanisms into a single record rather than adding a second.
How to check this
The SPF, DKIM and DMARC generator counts your lookups as you build the record and warns at eight, before the limit rather than after. It also flags the two-record mistake and the 255-character string limit. Once SPF is sound, the related decision is your enforcement policy — DMARC p=none vs quarantine vs reject covers how to move through it without bouncing legitimate mail.
Frequently asked questions
Which SPF mechanisms count toward the ten lookups?
include, a, mx, ptr and exists, plus the redirect modifier. ip4, ip6 and all cost nothing, which is why replacing an include with explicit IP addresses reduces the count.
Why did my SPF record break without me changing it?
The limit applies to the whole evaluation, including the includes nested inside your providers' records. If a provider restructures their own record, your total can cross ten with no change on your side. The check then returns permerror and the whole record is treated as invalid.