Skip to content
Start with 100 free verification credits
Qualisend
All articles
Guides / November 4, 2026

SPF too many DNS lookups: how to count and fix permerror

8 minutes read

Qualisend team
SPF too many DNS lookups: how to count and fix permerror

Your SPF record looks fine, every sender you use is listed, and yet one day a DMARC report or a bounce says permerror. The usual cause is the 10 DNS lookup limit: SPF is allowed to trigger only a fixed number of DNS queries while it is being evaluated, and each tool you add with an include: spends some of that budget. This guide shows how to count your lookups, which terms cost one and which are free, and the order in which to fix an over-limit record without breaking mail from a sender you forgot.

The short answer#

SPF is defined in RFC 7208, which says an implementation must limit the terms that cause DNS queries to 10 during evaluation. The terms that count are include, a, mx, ptr, exists and the redirect modifier. Terms that need no lookup, ip4, ip6 and all, are free. Counting is recursive: an include: costs one, plus everything inside the record it points to. Go over 10 and the check returns permerror, which means SPF does not pass for any mail from the domain. To fix it, delete includes for tools you no longer use, then replace what you can with ip4/ip6 for stable servers, then move bulk senders to a subdomain. Flatten only as a last resort. The free SPF, DKIM and DMARC checker and domain health check show the record you have published, but they do not follow includes or count lookups, so you count by hand as described below or use a tool that recurses.

What counts toward the limit#

TermCosts a lookup?Notes
include:domainYes, 1 plus its contentsThe included record is evaluated too, so its own includes count
a or a:domainYes, 1One term, no matter how many addresses it returns
mx or mx:domainYes, 1Easy to forget; you may not need it
ptrYes, 1Discouraged in the RFC; remove it
exists:domainYes, 1Rare, often used by macro-based setups
redirect=domainYes, 1 plus its contentsIgnored if the record also has an all term
ip4: and ip6:NoFree, but they must be kept up to date by you
allNoAlways last; terms after it are never evaluated

A concrete example shows how quickly it adds up.

example.com.  TXT  "v=spf1 include:_spf.google.com include:sendgrid.net include:mail.zendesk.com include:servers.mcsv.net mx a ~all"

That record has six lookup-costing terms at the top level, and each include: may contain more terms inside. The visible count is 6, the real count is whatever the nested records add. This is why a record that looks short can be over the limit, and why the number changes without you touching your DNS: a provider edits its own SPF record and your total moves.

The RFC also says implementations should limit "void lookups", queries that return nothing, to two. That is a recommendation rather than a hard requirement, but an include:, a or mx term that points at a name which no longer exists is exactly that kind of lookup. It is one more reason to remove dead includes first.

Step 1: confirm it is a count problem#

Before changing anything, rule out the other things that produce an SPF error.

  1. More than one SPF record. Two v=spf1 TXT records at the same name is also a permanent error, and it is easy to do by accident when a tool's setup page says to add a record. Run dig +short TXT example.com and count the lines that start with v=spf1. If you find two, merge them. When SPF, DKIM and DMARC stop working covers this and the other usual causes.
  2. A syntax error. A typo such as include without a domain, a bad ip4 range or a missing space breaks the record.
  3. A looping include. Two domains that include each other never finish evaluating.
  4. An include that points nowhere. The target domain publishes no SPF record at all.

If none of those apply, count lookups. Do it by hand once so you understand the tree: query the top-level record, list each costing term, then query every include: and redirect= target and repeat. A tool that follows includes does the recursion for you and is worth using, because a nested provider record can be several levels deep. The free checkers on this site read the record but do not count.

Step 2: remove what you no longer use#

This is the cheapest fix and it usually recovers several lookups. Go through every include: and ask whether anything still sends through it.

  • Trial tools. Services you tested for a month and never removed.
  • Retired platforms. The marketing tool you replaced two years ago, or the old helpdesk.
  • Providers you can only name from the include. If you cannot say what it is, find out before deleting. DMARC aggregate reports show which sources actually sent as your domain, so an include that never appears in a month of reports is a good candidate.

Delete one at a time, re-count, and keep the old record text so you can roll back. Also remove bare mx and a terms unless you really send from those hosts, and remove ptr entirely.

Step 3: replace includes with IP ranges, carefully#

For a sender with a small, stable set of addresses, such as your own mail server, you can swap an include: or mx for ip4: entries and save the lookups.

v=spf1 ip4:203.0.113.10 ip4:203.0.113.11 include:_spf.google.com ~all

The trade-off is maintenance. An ip4: entry is a promise that you will notice when the addresses change. Do this only for infrastructure you control. Never copy a large ESP's IP list into your own record: providers add and retire addresses without telling you, and your copy goes stale silently.

Step 4: move bulk and marketing senders to a subdomain#

Each sending domain has its own SPF record and its own budget. If your marketing platform, transactional service and support desk all send as example.com, they share one budget of 10. Give the newsletter a subdomain such as news.example.com, publish a short SPF record there, and set the platform to use it for the return path and From address. This also isolates reputation, which the sending subdomain guide explains in full.

Keep DMARC in mind when you do this. Alignment compares the From domain with the domain that passed SPF or DKIM. Relaxed alignment lets news.example.com align with example.com, but the sender still has to authenticate under one of those domains. Setting up DMARC covers alignment.

Step 5: flattening, and why it goes stale#

Flattening means replacing include: terms with the literal IP addresses they resolve to, so the record needs no lookups. It does work, and it is also the riskiest fix, because the include exists precisely so that the provider can change addresses without you editing DNS. A flattened record freezes the addresses at the moment you built it. When the provider adds a server, mail from it fails SPF until someone refreshes your record.

Two further limits apply. A flattened record can run past the size a single TXT record can comfortably hold, and DNS limits a UDP response, so large records need to be split or served carefully. And you now own a refresh job. If you flatten, do it with a service or script that re-resolves on a schedule and alerts you when it fails, never as a one-time copy and paste.

For most domains the order above is enough. Delete first, subdomain second, ip4 third, flatten last.

Keeping the count under control#

The lookup count is not fixed. It moves when you add a tool and when a provider edits its own record, so a record that passed in March can fail in September with no change from you. Three habits keep you ahead of it.

  • Count before you add. Check the total before adding any include, so you know whether the new sender fits.
  • Re-check on a schedule. Domain health checks recompute the recursive count every time.
  • Alert at 9, not at 11. By the time the count passes 10 you are already failing.

Domain Health Monitoring does the last two. Every covered domain gets a daily SPF check that follows includes and redirects and counts lookups the way RFC 7208 section 4.6.4 describes. It raises a warning at 9 or 10 lookups and a bad-severity issue above 10, and emails you when that happens. It also flags the other SPF problems from step 1: multiple records, syntax errors, an include that publishes no record, a +all or ?all ending and the ptr mechanism. One limit to know about: each report has a budget of 40 DNS queries per domain, so on a very large record some items show as not checked and the count is a lower bound. The wider case for checking more than SPF is in email domain health monitoring, and the provider-specific SPF guides show what each sender adds to your count.

Frequently asked questions

01What is the SPF 10 DNS lookup limit?

RFC 7208 says an SPF check must limit the terms that cause DNS queries to 10. The include, a, mx, ptr, exists and redirect terms count, and nested includes count too. Going over returns permerror, which receivers treat as an SPF failure.

02Do ip4 and ip6 mechanisms count toward the limit?

No. ip4, ip6 and all need no DNS query, so they are free. The cost is maintenance: you must update the addresses yourself whenever the sender changes them.

03Is flattening my SPF record a good fix?

It works, but it freezes the provider's current addresses, so mail fails when they add servers unless the record is refreshed. Try removing unused includes and moving bulk senders to a subdomain first, and flatten only with automated refresh.

04Why did my SPF break when I did not change anything?

Includes are evaluated recursively, so when a provider edits its own SPF record your total changes. A record at 9 or 10 lookups can tip over with no edit from you, which is why alerting before 10 is useful.


SPF only says which servers may send as you, and it cannot tell you whether the people on your list want to hear from you or even exist. The 100 free credits on the pricing page run the full verification on a list, so you can see how many addresses would bounce. A record that passes SPF still needs a healthy list to earn the inbox.

Your reputation, protected.

Clean your first list in minutes. 100 free credits, no card required.

Get started