Domain IP Lookup

How an email finds your mail server

Sender

you@gmail.com

MX lookup

who takes mail?

Mail server

priority 10 first

Inbox

delivered

Lowest priority number wins; higher numbers are backups

Troubleshooting

SPF's 10-Lookup Limit: What Counts and How to Stay Under It

5 min read

A receiving mail server checks SPF by evaluating your record, and evaluating it costs DNS queries. To keep that cost bounded, RFC 7208 caps how many query-causing terms one check may evaluate. Cross the cap and the result is permerror, a permanent error that is not a pass. Checkers commonly report it as “too many DNS lookups”, and it usually surfaces right after another sending service is added to the record.

What the specification counts

Section 4.6.4 of RFC 7208 lists the terms that cause DNS queries: the include, a, mx, ptr and exists mechanisms and the redirect modifier. Implementations must limit the total of those terms to 10 during one evaluation and must return permerror if the limit is exceeded. The all, ip4 and ip6 mechanisms need no query and are not counted, and neither is the exp modifier, which is only fetched later, after a failure.

TermCounts toward 10?Notes
includeYesPlus every counted term inside the record it points to
aYesOne lookup for the name
mxYesSeparately limited to 10 address lookups; more gives permerror
ptrYesDiscouraged: the RFC says it should not be published
existsYesOne query
redirectYesCounts when it is reached (only if no mechanism matched, and never when the record contains all); the target is then evaluated with the same budget
ip4, ip6NoThe address is in the record itself
allNoConventionally the last mechanism; anything after it is ignored
expNoFetched only after a failure, for the explanation string

Two details matter. First, include does not copy another record into yours: only its result is used, and the RFC admits the name was poorly chosen. A -all inside an included record does not end the overall evaluation. Second, mechanisms are evaluated from left to right and processing stops at the first one that matches. The limit applies to terms actually evaluated during a check, not to the size of the record on paper.

Counting a record by hand

Here is a hypothetical record for a company that uses two mail platforms, a CRM, a help desk and its own mail server:

A record that looks short and is not
v=spf1 include:mailer-a.example include:mailer-b.example include:crm.example include:helpdesk.example mx a ~all

Suppose the included records contain the terms below. They are invented for illustration, and real providers' records differ and change over time.

Term evaluatedLookups used so far
include:mailer-a.example1
inside it: include:_nets.mailer-a.example2
include:mailer-b.example3
inside it: a4
inside it: mx5
include:crm.example6
inside it: include:spf1.crm.example7
inside it: include:spf2.crm.example8
include:helpdesk.example9
mx10
a11: over the limit, permerror

Mail sent through the first platform matches early and passes. Mail from the server that only the last a authorizes needs an eleventh lookup, so the check returns permerror instead of a match. That asymmetry is why this fault looks intermittent: it depends on which sender's mail is being checked.

Other limits in the same specification

  • Void lookups. A query that returns no records, or a name error, is a void lookup. RFC 7208 recommends limiting them to two, and exceeding the limit produces permerror. Separately, an include: whose target has no SPF record, including a name that no longer exists, returns none, and the include mechanism turns that into permerror at once, so a stale include can break a record on its own.
  • Fan-out. An mx mechanism may not trigger more than 10 address lookups. For ptr, names beyond the first 10 are ignored.
  • One record only. If a domain publishes more than one record whose version is exactly v=spf1, the result is permerror.
  • Size. The RFC advises keeping the published record small enough that the answer fits in 512 octets, so it travels in a single UDP packet without EDNS(0).
  • Record type. SPF must be published as a TXT record. The dedicated SPF record type used in the experimental period has been discontinued.
  • Time. Receivers should limit the time spent on one evaluation but allow at least 20 seconds. If that time limit is exceeded, the result should be temperror, a temporary error, not permerror.

How to get back under the limit

  1. Delete what you no longer use. A cancelled service still costs a lookup whenever evaluation reaches its include. Removing dead includes is the cheapest fix.
  2. Move senders to subdomains. Each name has its own record and its own budget of 10. Mail whose envelope sender is on news.example.com is checked against that name's record, not the root's. Under relaxed alignment, DMARC still matches the subdomain to the organizational domain.
  3. Replace a and mx with literals when the servers are yours and rarely change. ip4 and ip6 cost nothing.
  4. Flatten with care. Flattening swaps an include for the addresses it currently resolves to. It passes today and fails silently when the provider changes its ranges.
  5. Drop ptr. The RFC says it should not be published. Swapping redirect for include saves nothing, since both count one lookup.
  6. Order by volume, but do not rely on it. Because evaluation stops at the first match, listing literals and your highest-volume senders first spends fewer lookups on most mail. That reduces how often the limit bites; it does not make an over-limit record valid, and it can hide the fault until a rarely used sender sends.

A permerror matters beyond SPF itself. DMARC (RFC 7489) passes when SPF or DKIM passes for an aligned domain, and permerror is not a pass, so SPF can no longer contribute. If DKIM is also missing or misaligned, the message fails DMARC. To see your own count, the SPF checker follows every include and redirect and counts the lookups across the whole tree against the limit of 10. That is a worst-case count of terms, not only the ones a given message would trigger. When you change the record, lower its TTL first so a mistake can be reverted quickly; see DNS TTL explained. For the wider picture, read SPF, DKIM and DMARC explained.

Key takeaway

Count terms, not characters: include, a, mx, ptr, exists and redirect each cost one lookup, nested ones included, and the eleventh makes the check return permerror.

Sources and further reading

Need to check a domain's public DNS addresses? Use the Domain IP Lookup tool.

Free tools for this topic

spf lookup limitspf permerrortoo many dns lookupsspf include mechanism

Frequently asked questions