Your SPF record looks fine, every service you use is listed, and yet a checker reports PermError: too many DNS lookups, or bounces mention "required too many lookups." This error means receivers stop evaluating your record partway through and treat SPF as failed, often for all of your mail. This guide shows how the limit is counted, how to find exactly where your lookups go, and four ways to get back under 10 without breaking a sender.
Key takeaways
- SPF allows only 10 DNS-querying lookups per evaluation, including nested includes, and going over causes a permerror that fails SPF.
- Remove includes for services you no longer use, and drop a and mx unless those hosts really send mail for your domain.
- Move third-party and bulk senders to subdomains, because each subdomain has its own SPF record and its own 10-lookup budget.
- Only flatten vendors with stable, documented IP ranges, and never flatten Microsoft 365 because its sending IP addresses change frequently.
What the limit is and why it exists
RFC 7208, the SPF specification, says implementations must limit the number of DNS-querying terms to 10 during a single SPF evaluation. If evaluation needs more, the result is permerror.
The limit exists to stop SPF from being used to make receivers flood DNS with queries. Because every receiving server enforces it, there is no way to raise it. You have to fit inside it.
What counts toward the 10
| Term | Counts? | Notes |
|---|---|---|
include: |
Yes | Plus everything inside the included record |
a / a:host |
Yes | |
mx / mx:domain |
Yes | Each MX host may also resolve up to 10 addresses |
exists: |
Yes | |
ptr |
Yes | And RFC 7208 says not to publish it at all |
redirect= |
Yes | |
ip4: / ip6: |
No | No DNS query needed |
all |
No | |
| The initial lookup of your own record | No |
The key word is nested. If you include a vendor whose record includes three more domains, that one include: costs you four lookups. Microsoft's SPF documentation spells this out: having fewer than 10 include: statements doesn't guarantee fewer than 10 DNS lookups.
The second limit: void lookups
RFC 7208 also says receivers should limit "void lookups," queries that return no records or a non-existent domain, to two. An include for a service you cancelled years ago, whose SPF record has since been deleted, is a void lookup. Two of those and you get permerror even if your total is under 10.
Step 1: count your real lookups
Start with your record:
dig +short TXT example.com | grep spf1
Say it returns:
"v=spf1 include:_spf.google.com include:spf.protection.outlook.com include:mailgun.org include:helpdesk.example-vendor.com include:crm.example-vendor.net a mx ~all"
Now look up each include and count what it contains:
dig +short TXT mailgun.org
"v=spf1 include:_spf.mailgun.org include:_spf.eu.mailgun.org -all"
That include costs 1 for mailgun.org, plus 1 each for the two nested includes, plus whatever those contain. Repeat for every include until you reach records that only contain ip4:/ip6:.
Write it down as a tree:
v=spf1 ... lookups
├─ include:_spf.google.com 1
├─ include:spf.protection.outlook.com 1
├─ include:mailgun.org 1
│ ├─ include:_spf.mailgun.org 1
│ └─ include:_spf.eu.mailgun.org 1
├─ include:helpdesk.example-vendor.com 1
│ └─ include:mail.example-vendor.com 1
├─ include:crm.example-vendor.net 1
│ ├─ include:a.crm.example-vendor.net 1
│ └─ include:b.crm.example-vendor.net 1
├─ a 1
└─ mx 1
total = 12 -> permerror
Vendor records change over time, so count against live DNS rather than trusting a number from a forum post. A free audit parses your SPF record and reports the lookup count along with your DKIM and DMARC status.
Why it sometimes "works anyway"
Receivers evaluate left to right and stop at the first match. Mail from Google might pass because _spf.google.com matches before the evaluator ever reaches lookup 11. Mail from the CRM at the end fails. That's why this error often shows up as "some of our emails fail" rather than "everything fails," and why it's easy to miss.
Step 2: remove what you don't need
This is the safest fix and usually gets you most of the way.
- Remove services you no longer use. Old newsletter tools, a previous help desk, a website host you left. These are also your likeliest void lookups.
- Drop
aandmxunless those hosts really send mail. With Google Workspace or Microsoft 365, your MX hosts are the provider's inbound servers, already covered by their include. On many recordsa mxcosts 2 lookups and authorizes nothing useful. - Delete
ptr. RFC 7208 says it should not be published. It's slow and unreliable. - Check for duplicates. Two includes that point to the same vendor under different names, or both a vendor's include and its IP ranges.
- Confirm each service actually uses your domain in the envelope sender. Many ESPs use their own bounce domain (or a subdomain you CNAME to them) for the
Return-Path. If so, SPF is checked on that domain, and their include on your root record does nothing. Check a sample message'sReturn-Pathheader before you keep an include "just in case."
That last point removes more includes than anything else. DMARC can pass through DKIM alignment alone, so a service that signs with DKIM for your domain doesn't also need to be in your root SPF record.
Step 3: move senders to subdomains
Each domain and subdomain has its own SPF record and its own 10-lookup budget. Microsoft recommends sending bulk and third-party mail from a subdomain anyway, so a problem with a vendor's mail doesn't affect your main domain's reputation.
; root domain: people's mailboxes only
example.com. TXT "v=spf1 include:spf.protection.outlook.com -all"
; marketing platform sends from news.example.com
news.example.com. TXT "v=spf1 include:servers.mcsv.net -all"
; help desk replies come from support.example.com
support.example.com. TXT "v=spf1 include:mail.example-vendor.com -all"
With DMARC's default relaxed alignment, mail with a From: of news@news.example.com still aligns with example.com's organizational domain, and your DMARC policy on the root covers subdomains unless you override it with sp=.
Many ESPs handle this through a "custom return path" or "branded sending domain" setting: you add a CNAME such as bounce.example.com pointing to the ESP, and their SPF applies to that subdomain automatically, costing you nothing on the root.
Step 4: flatten, carefully
Flattening means replacing an include: with the ip4: and ip6: ranges it currently resolves to. IP mechanisms don't cost lookups, so a flattened record can authorize a lot of senders.
Before:
v=spf1 include:_spf.google.com include:sendgrid.net include:crm.example-vendor.net ~all
After flattening the CRM vendor:
v=spf1 include:_spf.google.com include:sendgrid.net ip4:198.51.100.0/24 ip4:203.0.113.64/26 ~all
The catch: when the vendor adds or changes sending IPs, your copied list is out of date and their mail starts failing SPF without warning. Microsoft's guidance is useful here:
- Only flatten vendors with stable, documented IP ranges.
- Never flatten Microsoft 365 (
include:spf.protection.outlook.com). Microsoft says its sending infrastructure uses IP addresses that change frequently. The same applies to any large cloud provider. - Document what you flattened and when, watch vendor announcements, and review flattened entries at least quarterly.
Automated flattening services re-resolve includes on a schedule and update your record, usually by having you include a domain they host. That trades the manual work for dependency on a third party. Evaluate it like any other vendor with control over your mail authentication.
Also watch record length. Each TXT string is limited to 255 characters, and RFC 7208 says the whole SPF answer should fit within 512 bytes. A flattened record full of IP ranges can hit both limits, so split long values into multiple quoted strings and keep it lean.
A worked fix
Taking the 12-lookup example above:
- The helpdesk vendor sends with its own
Return-Pathand signs DKIM forexample.com. Remove its include: -2. aandmxpoint to Microsoft 365 inbound servers. Remove both: -2.- Move Mailgun to
mg.example.comwith its own SPF record: -3.
New root record:
v=spf1 include:_spf.google.com include:spf.protection.outlook.com include:crm.example-vendor.net ~all
Total: 5 lookups, with room left for the next tool someone signs up for.
After you fix it
- Re-test with a header check: send to Gmail, choose Show original, confirm
SPF: PASS. - Watch DMARC aggregate reports for a week. Any service that starts failing SPF and isn't covered by aligned DKIM will show up. See how to read DMARC reports.
- Make SPF changes a process. Whoever signs up for a new email-sending tool should check the lookup count before adding its include.
Frequently asked questions
Can I just split my SPF record into two TXT records?
No. Two v=spf1 records on the same name cause permerror immediately. You can split a long record into multiple quoted strings within one TXT record, but that only solves the 255-character limit, not the lookup limit.
Does include: on a subdomain count against my root domain?
Only if your root record includes that subdomain. A subdomain's own SPF record is evaluated separately when mail uses that subdomain in the envelope sender, with its own 10-lookup budget.
Is SPF flattening bad practice?
It isn't bad, but it has to be maintained. It works well for vendors with stable, published IP ranges and badly for large cloud providers whose IPs change. If you flatten, monitor and review regularly, or use a service that does it automatically.
Will the 10-lookup limit ever be raised?
There's no sign of it. The limit is part of the SPF standard and every major receiver enforces it. The practical answer is to rely more on DKIM, which has no such limit, and keep SPF small.
What to do next
Count your lookups against live DNS today, then remove dead and unnecessary includes before trying anything clever. If you're still over, move third-party senders to subdomains. Make sure each one also signs with DKIM for your domain, so DMARC passes even when SPF can't. For the basics of record syntax, see what an SPF record is.
Sources
More guides for your industry
Free checklist (PDF)
Free accountants website checklist
31 practical checks for accountants: website speed and mobile, Google Business Profile and reviews, email security, booking and enquiry handling, and AI search visibility. Each one says why it matters, and many link to a free tool that checks it.
Written by the MakeItFlow team
We build the website audit these guides are based on. Every fact is checked against the primary sources listed above . How we research and check
Check your own site in 30 seconds
Run a free audit covering speed, SEO, DNS, email authentication and security headers — and get a prioritised fix list.