Skip to main content
← Back to all posts
Email Authentication · 12 min read

SPF PermError: too many DNS lookups, and how to fix it without flattening.

Your SPF record is allowed ten DNS lookups. Not ten entries, not ten characters - ten queries, counted across every vendor you delegate to. Cross it and the record does not degrade, it stops. Here is what counts, how to spot it in a header, and the five fixes ranked by what we would actually recommend.

By EmailSheriff · · 12 min read · Technical
10
DNS lookups allowed per SPF evaluation, total
0
lookups an ip4: mechanism costs you
9
lookups a typical four-include record already spends
1
SPF record allowed per domain - two is an instant PermError

1. What actually happens when SPF hits eleven

Your SPF record does not get truncated. It does not partially apply. It does not fall back to a more permissive result. The receiving mail server stops evaluating, returns PermError, and then makes a decision that has nothing to do with whether the sending server was legitimate.

This is the part most people miss. PermError is not the same as fail. A fail means "this server is not authorised to send for this domain" and receivers know exactly what to do with it. PermError means "your record is broken and I could not finish reading it," and every receiver handles that differently.

Gmail treats a PermError as an SPF non-result. If you have DMARC at p=reject and DKIM is also failing, the message is gone. Microsoft is stricter and will often junk on PermError alone. Some corporate gateways reject at SMTP time. Others ignore it entirely.

So the symptom is maddening: mail lands fine at some domains, vanishes at others, and nothing in your sending setup changed. You did not touch DNS. Your ESP did.

Why this breaks without warning

You almost never cross the limit yourself. You cross it because a vendor you use added a hostname to their include, six levels down a chain you have never looked at. Your record is byte-for-byte identical to what it was last month. It now returns PermError.

We have watched support tickets that ran for three weeks on this. The sender is convinced the problem is their ESP, their content, or their domain reputation, because the one thing that definitely did not change is the SPF record they wrote.

2. The rule, precisely

The limit lives in RFC 7208, section 4.6.4. The wording matters, so here is what it actually says in plain terms:

During evaluation of a single SPF check, the total number of mechanisms and modifiers that cause a DNS query must not exceed ten. Cross that ceiling and the check must return PermError immediately.

Two things about that sentence trip people up constantly.

First, it counts lookups, not characters, and not entries in your record. A record with four include: statements can easily consume nine lookups, because each include is evaluated recursively and everything inside it counts against the same budget of ten. There is no per-level allowance. It is one shared pool for the entire tree.

Second, the ten is a ceiling on queries issued, not queries that returned something. A lookup that returns NXDOMAIN still spent budget.

What counts against the ten

MechanismCounts?Notes
include:YesOne, plus everything inside it, recursively
a / a:domainYesOne per mechanism
mx / mx:domainYesOne for the MX query, and see the trap below
ptrYesDeprecated. Do not use it. Ever.
exists:YesOne per mechanism
redirect=YesCounts, and the target's lookups count too
ip4: / ip6:NoLiteral addresses. Free. Unlimited.
allNoTerminal mechanism, no query
exp=NoOnly fetched on failure, outside the budget

The line to internalise: ip4: and ip6: are free. Every fix in this article is ultimately some version of converting expensive lookups into free literals.

The MX trap nobody mentions

An mx mechanism costs one lookup for the MX query itself. But RFC 7208 also caps the number of MX records that get resolved at ten, and each of those A-record resolutions is subject to its own limit. A domain with twelve MX hosts will return PermError on the mx mechanism alone, before a single include has been touched.

Rare, but we have seen it, and it is genuinely baffling when it happens because the record looks trivially short.

3. A worked example: how a four-entry record spends nine lookups

Here is a record that looks completely reasonable. A company using Google Workspace for internal mail, HubSpot for marketing, and SendGrid for transactional.

The record as published
v=spf1 include:_spf.google.com include:_spf.hubspot.com include:sendgrid.net include:servers.mcsv.net ~all

Four includes. Under a hundred characters. And it is one vendor change away from breaking. Count what a receiver actually resolves:

What the receiver resolves
# 1 include:_spf.google.com # 2 └ include:_netblocks.google.com # 3 └ include:_netblocks2.google.com # 4 └ include:_netblocks3.google.com # 5 include:_spf.hubspot.com # 6 include:sendgrid.net # 7 └ include:sendgrid.net (nested netblocks) # 8 include:servers.mcsv.net # 9 └ include: (Mailchimp netblock expansion) total: 9 of 10 ← one lookup of headroom

Nine. One spare. Now the marketing team signs up for a webinar platform and adds a fifth include. That is ten or eleven, depending on the vendor's own chain, and the record breaks. Or nobody adds anything, Google restructures their netblocks, and it breaks anyway.

This is why "my SPF record is short" is not a defence. The length of what you wrote tells you nothing about the cost of what gets evaluated.

Check yours before you read further

Our DNS Checker walks the full include chain and shows you the resolved count with the tree, so you can see exactly which vendor is eating your budget rather than guessing. It is free and needs no signup. If you are at eight or nine, you are not safe. You are one vendor decision from an outage.

4. How to diagnose it properly

Three signals, in the order you will usually meet them.

Signal one: the header says so

Ask anyone who received your mail for the raw headers and look at Authentication-Results. You are looking for this:

Authentication-Results: mx.google.com; spf=permerror (google.com: domain of [email protected] exceeded the maximum number of DNS lookups) [email protected]

Different receivers word it differently. Microsoft says permerror with a Reason: too many DNS lookups. Some gateways just say spf=permerror with nothing further. The word permerror is the tell. Our Header Analyzer will decode this for you if the raw text is hard to read.

Signal two: the pattern of failures

PermError produces a signature that is easy to recognise once you know it. Delivery is inconsistent by receiving domain, not by recipient, not by content, not by time of day. Gmail is fine, Outlook junks, a client on Proofpoint bounces outright. If your delivery problems sort cleanly by the recipient's mail provider, suspect SPF before you suspect anything else.

Signal three: DMARC aggregate reports

If you have a DMARC record with a rua= address, the XML reports contain per-message SPF results. A sudden block of permerror rows against your own legitimate sending IPs is conclusive. This is the fastest signal available, and it is the argument for publishing DMARC even at p=none before you need it.

5. The five real fixes, ranked

Ranked by how much we would actually recommend them, not by how often they get suggested.

Fix 1: Delete what you are not using

Start here. Every time. Open your SPF record and, for each include, answer one question: did anything send mail through this in the last ninety days?

In our experience most records carry at least one dead include. The trial ESP from 2023. The survey tool the marketing lead used once. The ticketing system you migrated off. Each of those is one to three lookups you are paying for and getting nothing from.

This fix costs nothing, breaks nothing if you check properly, and resolves the problem outright more often than people expect. Do it before you consider anything below.

Fix 2: Move to subdomains

This is the structurally correct answer and the one we would push hardest if you have the time to do it.

SPF is evaluated per sending domain. Nothing requires all your mail to leave from the same one. Send marketing from mail.yourdomain.com, transactional from send.yourdomain.com, and keep the root for human mail. Each subdomain gets its own SPF record with its own budget of ten.

Before: one record, nine lookups, fragile
yourdomain.com TXT "v=spf1 include:_spf.google.com include:_spf.hubspot.com include:sendgrid.net include:servers.mcsv.net ~all"
After: three records, none above four
yourdomain.com TXT "v=spf1 include:_spf.google.com ~all" # 4 mail.yourdomain.com TXT "v=spf1 include:_spf.hubspot.com ~all" # 1 send.yourdomain.com TXT "v=spf1 include:sendgrid.net ~all" # 2

The bonus is reputation isolation, and it is a bigger deal than the lookup fix. If a marketing campaign gets a wave of complaints, the damage is scoped to mail.yourdomain.com. Your invoices and password resets keep landing. Every large sender does this. Very few small ones do.

The cost is real: you have to reconfigure each platform to send from the new subdomain, set up DKIM per subdomain, and make sure DMARC alignment still holds. Budget an afternoon, not ten minutes.

Fix 3: Replace one include with its IPs

If a vendor publishes a stable, small block of addresses, you can inline them and skip the lookup entirely.

Before: one lookup
include:smallvendor.example
After: zero lookups
ip4:198.51.100.0/24 ip4:203.0.113.16/28

Do this selectively and only for vendors whose ranges genuinely do not move. Never do it for Google, Microsoft, Amazon SES or anyone else operating at hyperscale, because their netblocks change and you will not be told.

Fix 4: SPF flattening, with the warning attached

Flattening means resolving every include down to raw IPs and publishing the flat list. It works. It reliably takes you to zero lookups. Plenty of vendors will sell it to you as a service.

We think most people should not do it, and here is the honest reasoning.

An include is a subscription to a vendor's list of sending IPs. When Google adds a netblock, your record picks it up automatically because you delegated that decision to them. Flattening cancels the subscription. You now own a snapshot, and snapshots go stale silently. The vendor adds an IP, sends your mail from it, and your own SPF record fails your own mail.

Automated flattening services re-resolve on a schedule and update your record for you, which addresses the staleness. But you have now made a third party's uptime a hard dependency of your mail authentication, and you have added a recurring bill to fix a problem that fix 1 or fix 2 usually solves for free.

Flattening is a reasonable last resort when you genuinely cannot restructure. It is a poor first move.

Fix 5: Consolidate vendors

Not a DNS fix, and not one you will action today. But if your SPF record needs nine lookups, that is a fact about your stack. Four tools sending mail on your behalf is four vendors who can break your authentication, four DKIM keys to rotate, and four reputations tangled into one domain. The lookup limit is the symptom. Worth a conversation.

6. What each vendor actually costs you

Nobody publishes this, so here is the table people keep asking for. These are the resolved lookup counts for the vendors that show up most often in the records we see. Counts drift when providers restructure, so treat these as a planning guide and measure your own.

VendorIncludeTypical costNotes
Google Workspace_spf.google.com4One include plus three nested netblock records
Microsoft 365spf.protection.outlook.com1–2Flat. One of the cheapest at scale.
HubSpot_spf.hubspot.com2–3Behind a redirect=. Counters that skip redirects report this wrong.
Salesforce_spf.salesforce.com2–4Varies by instance and region
Mailchimpservers.mcsv.net2Nested netblock expansion
SendGridsendgrid.net2Nested
Amazon SESamazonses.com1Flat, but region-specific
Zoho Mailzoho.com1–2Varies by data centre (.eu, .in)
Zendeskmail.zendesk.com1Flat
ActiveCampaignemsd1.com1Flat

Read that table and the arithmetic gets uncomfortable fast. Google Workspace plus HubSpot plus Mailchimp is already eight or nine. That is a completely ordinary stack for a twenty-person company, and it is sitting on the edge with no warning anywhere in any admin console.

Google Workspace is the expensive one

If you run Google Workspace, four of your ten lookups are gone before you add a single marketing tool. This is the single most common reason a small company hits the limit, and there is no way to reduce it while keeping the include, because Google's netblocks genuinely do change and inlining them will break your mail eventually.

The fix is structural, not clever: keep _spf.google.com on your root domain for human mail, and move every marketing and transactional platform to subdomains. Google gets its four lookups on a record where nothing else is competing for budget.

Microsoft 365 is the cheap one

Microsoft publishes a comparatively flat record, so spf.protection.outlook.com usually costs one or two. If you are on Microsoft 365 and still hitting the limit, the cause is almost certainly accumulated vendor includes rather than your mail platform.

HubSpot hides behind a redirect

Worth calling out separately because it produces wrong answers in tools. HubSpot's record uses redirect= rather than listing includes directly. Any lookup counter that does not follow the redirect will tell you HubSpot costs one lookup. It does not. Ours follows redirects, which is how we found this.

7. Four mistakes we see constantly

Publishing two SPF records

A domain must have exactly one TXT record starting with v=spf1. Two records is an immediate PermError under RFC 7208, and it is not a lookup problem, so it does not show up in lookup counters. It usually happens when someone adds a vendor's suggested record instead of merging the vendor's include into the existing one. Merge, never append.

Using ptr

The ptr mechanism is formally deprecated. It is slow, it is unreliable, some receivers ignore it, and it burns lookups. If it is in your record, delete it. There is no situation in 2026 where it is the right answer.

Assuming -all fixes deliverability

Moving from ~all to -all is a hardening step, not a delivery fix. If your record is already returning PermError, the qualifier at the end is never reached, because evaluation stopped. Fix the lookups first. Tighten afterwards.

Forgetting the redirect chain

A redirect= modifier costs a lookup and drags its target's entire chain into your budget. HubSpot is the canonical example: hubspot.com publishes v=spf1 redirect=_hspf.hubspot.com, and every include lives behind that redirect. Lookup counters that do not follow redirects will report a comfortable number and be completely wrong. Ours follows them, because we got this wrong once and fixed it.

8. The fix, in order

  1. Count what you actually have. Run your domain through a checker that follows both includes and redirects. Write down the number.
  2. Delete dead includes. Ninety-day rule. This alone frequently ends the problem.
  3. Re-count. If you are at seven or below, stop. You are done, and you have headroom.
  4. Split by subdomain if you are still above seven. Marketing, transactional, human mail.
  5. Inline small stable vendors as ip4: literals. Never the hyperscalers.
  6. Verify from the receiving end. Send to a Gmail address and a Microsoft address, pull the headers, confirm spf=pass on both. A checker tells you what should happen. Headers tell you what did.
  7. Set a calendar reminder for ninety days. Your record will drift. Everyone's does.
If you remember one thing

The SPF lookup limit is not a rule about how long your record is. It is a budget spent by everyone you delegate to, most of whom will never tell you when they spend more of it. Leave headroom, check quarterly, and treat eight as your ceiling rather than ten.

9. Frequently asked questions

What is the SPF 10 DNS lookup limit?

RFC 7208 section 4.6.4 caps the number of DNS-querying mechanisms evaluated during a single SPF check at ten. The mechanisms that count are include, a, mx, ptr, exists and redirect. Exceed ten and the check returns PermError instead of pass or fail. The limit exists to stop a single SPF evaluation from being turned into an amplified denial-of-service attack against DNS infrastructure.

How do I fix "SPF PermError: too many DNS lookups"?

In order of preference: remove includes for services you no longer use; split sending across subdomains so each gets its own budget of ten; replace small stable vendors with their ip4: ranges; and only as a last resort, flatten the record to raw IPs. Removing dead includes resolves it more often than any other single step, and costs nothing.

Does ip4: count toward the SPF lookup limit?

No. Literal ip4: and ip6: mechanisms require no DNS query, so you can list as many as you like without touching the limit. The practical constraint is the 512-byte DNS response size, beyond which the record splits across multiple strings. That is a separate issue and much less likely to bite you.

Is SPF flattening safe?

It works, but it trades one risk for another. Flattening replaces a live subscription to your vendor's IP list with a static snapshot. When the vendor adds a sending IP, your record does not know, and your own mail starts failing SPF. Automated flattening services re-resolve on a schedule to mitigate this, at the cost of making a third party a hard dependency of your authentication. We recommend it only when restructuring genuinely is not possible.

Why did my SPF record break when I did not change it?

Because you are not the only person who can change its cost. Every include: delegates part of your lookup budget to a vendor. When that vendor adds a nested include to their own record, your resolved total rises without your record changing by a single character. Records sitting at nine lookups break on somebody else's schedule.

Does PermError mean my email will definitely go to spam?

No, and that is what makes it hard to diagnose. PermError is treated as an SPF non-result, and receivers handle it inconsistently. Gmail is relatively tolerant if DKIM passes and DMARC aligns. Microsoft frequently junks on PermError alone. Some corporate gateways reject at SMTP time. The result is delivery that looks fine at some domains and fails at others, which sends people hunting for content or reputation problems that do not exist.

Can I have more than one SPF record?

No. A domain must publish exactly one TXT record beginning with v=spf1. Two or more is an immediate PermError regardless of lookup count. When a new vendor gives you an SPF record to add, merge their include: into your existing record rather than publishing a second one.

Count your real SPF lookups in ten seconds

Our DNS Checker walks the full include chain, follows redirects, and shows the resolved tree with the exact count. Free, no signup, and it names the vendor eating your budget.

Check your SPF record →
+ Related tools
DNS Checker
Walks your full SPF include chain, follows redirects, shows the real lookup count.
Header Analyzer
Paste raw headers and read the Authentication-Results line in plain English.
Deliverability Score
One score across reputation, authentication and infrastructure - with the fixes.