The SPF 10 DNS Lookup Limit, Explained Properly

Why RFC 7208 caps SPF at 10 DNS-querying mechanisms, exactly which parts of your record count toward that number, and what actually happens the moment you go over.

📅 Published August 2026· ⏳ 15 min read· ✍️ ToolsNovaHub Editorial Team
🛠️ Related tool: Open SPF Lookup →

What the Limit Actually Protects Against

SPF was designed at a time when mail servers already had plenty of reasons to be cautious about how much work an inbound message could trigger before it was even accepted. Every SPF check requires the receiving server to go out, query DNS, interpret what comes back, and sometimes query DNS again based on that answer. Without a ceiling, a malicious or simply badly configured domain could publish an SPF record that forces every mail server on the internet receiving its mail to perform dozens or hundreds of recursive DNS lookups on every single message — a cheap, repeatable way to waste other people's infrastructure. RFC 7208 closes that door with a flat, non-negotiable number: 10 DNS-querying mechanisms per SPF check, no exceptions.

It's worth being precise about what "10" actually refers to, because this is where most people misjudge their own record. It isn't 10 characters, 10 IP ranges, or 10 lines in the TXT record. It's 10 mechanisms that individually trigger a DNS lookup during evaluation, counted as the validator walks through your record and any records it points to, recursively, left to right, until it either finishes evaluating or hits the ceiling.

ToolsNovaHub Pro Tip
Run a fresh count every time you add a new email vendor, not just when deliverability starts breaking. Vendors update their own SPF includes over time, and a record that was safely at 7 lookups can drift to 11 without you touching your own DNS zone at all.
⚠️
Common Beginner Mistake
Assuming ip4 and ip6 entries count toward the limit the same way include does. They don't — literal IP ranges are free. The lookup budget is only spent by mechanisms that require SPF to go back out to DNS to find out more.

Which Mechanisms Count, and Which Don't

MechanismCounts Toward the 10?Why
include:Yes — 1 per occurrenceFetches another domain's TXT record and evaluates it recursively
aYes — 1 per occurrenceRequires an A/AAAA lookup for the domain (or specified domain)
mxYes — 1, plus 1 per returned MX hostFirst resolves MX records, then resolves each host's own address
ptrYes — 1 per occurrence, deprecatedRequires a reverse DNS lookup, explicitly discouraged by RFC 7208
exists:Yes — 1 per occurrencePerforms an A lookup purely to test existence, often used with macros
ip4: / ip6:NoLiteral address ranges evaluated with no DNS query at all
allNoA fixed terminal match with no lookup required
redirect=Yes — 1, replaces the record entirelyFetches and evaluates a different domain's record in place of the rest of the current one

Counting a Real Record by Hand

Take a fairly ordinary small-business SPF record: v=spf1 include:_spf.google.com include:sendgrid.net include:spf.protection.outlook.com a mx ~all. On the surface that's four countable mechanisms — two includes, an a, and an mx — which looks comfortably under 10. But each include doesn't just cost 1; it costs 1 plus whatever the target domain's own record costs when evaluated. Google's _spf.google.com alone typically resolves through several nested includes internally, and Microsoft's Outlook include does the same. By the time recursive evaluation finishes, that four-mechanism-looking record can easily land at 9 or 10 real lookups, sometimes more depending on what those vendors currently publish.

This is exactly why manually eyeballing a record's top-level mechanism count is unreliable. The only trustworthy way to know your real number is to trace every include recursively, the same way a validating mail server would, which is precisely what a proper SPF checking tool does automatically.

📋
Direct Mechanisms
Only count what's literally written in your own TXT record first — these are the easy, visible lookups.
🔁
Nested Mechanisms
Every include you reference has its own record, and that record's countable mechanisms are added to your total.
🔍
Void Lookups
Track separately: any lookup returning nothing counts against a stricter 2-lookup void sub-limit, regardless of the main count.

The Void Lookup Limit Is a Separate Trap

Beyond the headline number of 10, RFC 7208 defines a second, stricter limit that catches people off guard even more often: no more than 2 of your lookups are allowed to come back completely empty — an NXDOMAIN or a query with zero answers. This exists specifically to stop a different kind of abuse: a record engineered to force the evaluator to repeatedly query domains that don't exist, wasting resolver time on failed lookups rather than useful ones. A record with a typo'd include domain, or one referencing a mail vendor's SPF hostname that was since retired, can trip this limit well before the main count of 10 becomes relevant.

What Happens the Moment You Cross 10

SPF evaluation is not tolerant of exceeding the limit in any partial or graceful way. The moment the evaluator would need to perform an 11th DNS-querying mechanism, RFC 7208 mandates the result is permerror, full stop — not a fallback to neutral, not "best effort" against the first 10. A permerror tells the receiving mail server that your domain's SPF record is, from a technical standpoint, broken, and RFC 7208 explicitly notes that receivers may choose to reject mail on a permerror rather than accept it, exactly the outcome a properly configured SPF record was supposed to prevent.

In practice this means a record that worked fine for months can start silently failing the moment a single vendor's include grows by one more nested lookup on their end — something entirely outside your control, and something that won't show up until deliverability quietly drops and someone finally goes and reads the aggregate DMARC reports.

Realistic Ways to Fix a Record That's Over the Limit

FixEffortTrade-off
Remove unused vendor includesLowFastest win; requires an honest audit of who actually sends mail on your behalf today
Replace mx with explicit ip4/ip6 entriesLow–MediumRemoves a lookup but needs updating if your mail server IPs change
Flatten one or two heavy includes into static IPsMediumCuts lookups sharply, but requires a process to re-sync IPs when the vendor changes theirs
Consolidate to fewer, better-chosen vendorsHighBest long-term fix, but requires actual operational or contractual changes

Testing Before You Publish a Change

Any time you edit an SPF record specifically to address a lookup-count problem, verify the new count before treating the fix as done — not after DNS propagation completes and mail starts flowing again, but immediately, against the exact record text you're about to publish. A validator that recursively resolves every include the way a real receiving server would is the only reliable way to confirm you're safely under both the 10-lookup ceiling and the 2-void-lookup sub-limit at the same time, since fixing one without checking the other is a common half-fix.

Why 10 and Not Some Other Number

People sometimes assume the number 10 was picked to be generous, room for a handful of vendors plus your own infrastructure. In reality it reads more like a compromise between two competing pressures the working group had to balance. Set the ceiling too low and legitimate organizations with several genuinely necessary mail-sending vendors would be structurally unable to publish a compliant record without resorting to workarounds. Set it too high and the protection against amplification — a small SPF check triggering a large amount of downstream DNS work — becomes meaningless. Ten sits at a point where a well-run small-to-mid-size organization can usually fit their real needs in, while a record trying to authorize dozens of loosely-tracked senders gets pushed toward consolidation, which is arguably a healthier outcome for the sender's own security posture anyway. A domain with an SPF record that would need 30 or 40 lookups to fully express probably has a sprawling, poorly audited set of authorized senders regardless of what SPF's limit says.

How the Evaluator Walks Through Your Record

It helps to actually picture the evaluation order, because it explains some behavior that otherwise looks confusing. SPF evaluation is strictly left to right through the mechanisms in your top-level record. When it hits an include, it doesn't finish reading your record first and then go check the include afterward — it pauses right there, fetches the target record, and recursively evaluates that record's mechanisms in the same left-to-right order, including any nested includes inside it, before returning to continue with whatever comes after your original include mechanism. This is why the running lookup count is a depth-first tally, not a breadth-first one: a single include with three levels of nesting inside it is fully resolved, lookups and all, before the evaluator ever looks at your record's second mechanism.

This also explains why placement matters for efficiency even though it doesn't change correctness. If your highest-volume vendor's include sits last in the record, and every one of your other mechanisms needs to be checked and fail to match before reaching it, then the "average case" lookup cost for your actual mail traffic is higher than the record's theoretical maximum would suggest, since most real checks are walking past several non-matching mechanisms first.

A Second Worked Example: Where the Count Sneaks Up

Take a record that looks deceptively safe: v=spf1 a mx include:_spf.google.com include:mailchimp.com include:eu.hs-send.com include:mktomail.com ~all. Counted naively at the top level, that's six mechanisms: a, mx, and four includes. Already close to the ceiling before any nesting is considered. Now expand each one. The a mechanism costs 1. The mx mechanism costs 1 plus one more for every MX host your domain publishes — two MX records means mx alone costs 3, not 1. Google's include typically resolves through two additional nested includes internally. Mailchimp's, HubSpot's regional sending domain, and Marketo's each carry their own internal structure too, some flatter than others. It's entirely plausible for this record, which looks like six lines, to resolve to 13 or more actual lookups once fully expanded — already a permerror, and one that would only be caught by actually tracing the whole tree rather than glancing at the record text.

Auditing on a Schedule, Not Just When Something Breaks

Because a large share of the lookup total lives inside domains you don't control, a record that passes today is not a guarantee it passes next month. Vendors restructure their SPF infrastructure more often than most domain owners expect — adding regional sending pools, splitting a single flat list into several nested includes for internal reasons, or migrating between infrastructure providers entirely. None of that requires you to touch your own DNS zone, and none of it produces a notification to you when it happens. The only way to catch a slow creep toward the ceiling before it becomes a live permerror is a periodic re-check, ideally automated, of the exact lookup total your record currently resolves to.

The Amplification Problem SPF Was Designed Around

To really understand why a hard ceiling was necessary rather than just a soft recommendation, it helps to think about the asymmetry involved. Publishing an SPF record costs the domain owner essentially nothing — a single DNS TXT entry, updated whenever needed. But every single piece of mail claiming to be from that domain, arriving at every mail server on the internet, triggers whatever DNS work that record demands. A domain that publishes a record requiring 50 recursive lookups isn't spending 50 lookups' worth of resources itself; it's forcing every receiving mail server, everywhere, to spend that much, on every message, indefinitely. That's a genuine amplification vector, structurally similar in spirit to other DNS-based amplification problems the internet has had to design around elsewhere. A flat, universal ceiling that every implementation enforces identically closes that door completely, rather than relying on individual receivers to each independently decide what a "reasonable" number of lookups looks like.

How Different Receivers Actually Handle the Ceiling in Practice

RFC 7208 mandates the permerror result when the ceiling is exceeded, but it deliberately leaves what happens next up to local policy at the receiving server. In practice, the large mailbox providers you're most likely to care about tend to treat a permerror as a meaningfully negative signal, often folding it into broader reputation and filtering decisions rather than issuing a hard, deterministic bounce every time. Smaller or more strictly RFC-compliant mail systems are more likely to reject outright on a permerror. This variance means the practical consequences of exceeding the limit aren't perfectly uniform across the mail ecosystem, but it also means you can't rely on "well, my mail to Provider X still seemed to go through" as evidence a permerror isn't actually happening — different providers make different choices about how visibly they penalize it, and a record that's technically broken today may just not have produced an obviously broken outcome at whichever provider you happened to test against.

Lookup Counting for MX Records With Many Hosts

The mx mechanism deserves a closer look because its lookup cost is the least intuitive of the countable mechanisms. Writing mx alone in a record doesn't cost a flat 1; RFC 7208 specifies that it costs 1 for the initial MX record lookup, plus one additional lookup for each of the resulting MX hostnames as their own A/AAAA records get resolved. A domain publishing three MX records, common for redundancy, means the mx mechanism alone consumes four lookups from your ten-lookup budget: one to fetch the MX list, three more to resolve each listed host. This is a specific, easy-to-miss detail, because a record's author often writes mx expecting it to behave like ip4 or a — a flat, predictable cost — when its actual cost scales directly with how many mail servers the domain happens to publish, information that isn't visible just by reading the SPF record text itself.

The Practical Difference Between a and mx in Terms of Lookup Risk

MechanismTypical Lookup CostRisk Factor
aFlat 1, regardless of how many A/AAAA records the domain hasLow and predictable
mx1 plus 1 per MX host, scales with your own mail redundancy setupModerate, worth checking directly against your actual MX record count
a:otherdomain.comFlat 1, resolves a specified domain instead of the current oneLow, but depends on a domain you may not control staying stable

How the 10-Lookup Ceiling Interacts With DNSSEC-Signed Zones

For domains running DNSSEC, it's worth knowing that DNSSEC validation itself doesn't add to the SPF lookup count — the ceiling counts SPF-specific mechanism lookups as defined by RFC 7208, not the underlying DNSSEC chain-of-trust verification work a validating resolver might separately be doing to authenticate each response. The two systems operate independently: DNSSEC governs whether a receiving server can trust that the DNS answers it received weren't tampered with in transit, while the SPF lookup ceiling governs how many of those answers a single SPF evaluation is allowed to request in the first place. A domain can run a fully DNSSEC-signed zone and still exceed the SPF lookup ceiling in exactly the same way an unsigned zone would, and fixing one has no bearing on the other.

Void Lookups Deserve Their Own Careful Walkthrough

The void lookup sub-limit is easy to skim past as a footnote to the main 10-lookup ceiling, but it operates on genuinely different logic and deserves to be understood on its own terms. A void lookup isn't about how many mechanisms you have; it's specifically about how many of your countable lookups come back with nothing at all — either an NXDOMAIN response (the queried name doesn't exist in DNS) or a response with zero answer records for the query type SPF needs. RFC 7208 caps this at 2 for the entirety of a single SPF evaluation, counted across every level of nesting, independent of the main 10-lookup tally. A record could theoretically have only 4 total lookups, comfortably under the main ceiling, and still permerror if 2 of those 4 happen to resolve to nothing.

The rationale mirrors the main limit's amplification concern but targets a slightly different abuse pattern: a record engineered to reference a long chain of intentionally non-existent domains forces a validating resolver to spend time on failed lookups specifically, which behave differently in terms of caching and resolver load than successful ones. Capping void lookups at 2 closes that variant of the same underlying concern.

Common, Entirely Accidental Sources of Void Lookups

✍️
Typo'd Include Hostname
A single mistyped character in a vendor's SPF include hostname is enough to turn a valid lookup into a void one.
🗑️
Retired Vendor Domain
A vendor that fully decommissioned their old SPF hostname during a migration, with the domain no longer resolving at all.
🔄
Copy-Paste From Outdated Docs
Following an old blog post or forum answer referencing a vendor's SPF include hostname from several years ago that's since changed.

How to Actually Check Your Void Lookup Count

Unlike the main lookup count, which you can reason about by simply tallying mechanism types, checking for void lookups requires actually resolving each countable mechanism and inspecting whether the response came back empty. This is not something you can determine by reading the record's text alone — two records with identical syntax could have completely different void-lookup outcomes depending on whether their referenced domains currently resolve. A proper validator performs this resolution automatically and reports it as a distinct figure alongside the main lookup count, which is the only reliable way to know your actual exposure without manually querying every single include, a, mx, ptr, and exists target by hand and checking each response individually.

Historical Context: How the 10-Lookup Figure Was Chosen

Understanding a bit of the standards history behind SPF's lookup ceiling helps explain why it's treated as a hard, non-negotiable number rather than a soft guideline implementations are free to interpret differently. Earlier drafts of SPF's specification, before RFC 4408 and later RFC 7208 formalized the current rules, went through substantial community debate about exactly this kind of resource-bounding question, since SPF was one of the first widely deployed DNS-based email authentication mechanisms and the working group had limited prior art to draw on for how aggressively to bound recursive DNS work. The eventual consensus settled on a fixed number specifically because a fixed, universally enforced ceiling is far more useful for interoperability than a vague "reasonable amount" left to each implementation's own judgment — without a specific number, different mail servers could disagree about what's acceptable, producing exactly the kind of inconsistent, hard-to-diagnose behavior a protocol aiming for broad interoperability needs to avoid.

Comparing SPF's Approach to Other Email Authentication Protocols' Resource Bounds

ProtocolResource-Bounding Mechanism
SPFHard 10-lookup ceiling plus a separate 2-void-lookup sub-limit
DKIMNo equivalent DNS-lookup ceiling; a signature references exactly one selector, one lookup
DMARCRelies on SPF and DKIM's own bounds; adds no independent DNS-lookup ceiling of its own

This comparison highlights something worth understanding: SPF's lookup-recursion problem is fairly specific to its own mechanism design, where a single record can reference other records that reference still more records. DKIM's simpler, single-selector-per-signature lookup model doesn't have an equivalent recursive expansion problem, which is exactly why DKIM has no comparable ceiling to worry about — it's not that DKIM's designers considered and rejected a limit, but that DKIM's lookup structure never created the same category of risk SPF's recursive include mechanism does.

What a Full Recursive Trace Output Actually Looks Like

It's worth seeing what a genuinely complete recursive trace looks like, rather than just describing the process abstractly, since this is exactly the kind of output a proper validation tool should surface. For a record like v=spf1 include:_spf.google.com include:sendgrid.net ~all, a full trace would report something structured roughly like: top-level record, 2 include mechanisms found. Resolving include:_spf.google.com → found 3 nested includes, 0 direct ip4/ip6 → recursing. Resolving each of those 3 → 2 return only ip4/ip6 ranges (0 further lookups each), 1 returns 1 more nested include → recursing further → that final layer returns only ip4/ip6 ranges. Running total from the Google chain: 5 lookups (1 initial + 3 second-level + 1 third-level). Resolving include:sendgrid.net → found 0 nested includes, direct ip4/ip6 ranges only → 1 lookup. Grand total: 6 lookups, comfortably under the 10-lookup ceiling, with 4 lookups of headroom remaining. This level of explicit, layer-by-layer accounting is what separates a genuinely trustworthy validation result from a superficial one that only reports the final number without showing its work.

Why the Lookup Limit Sits at the SPF Layer and Not at the DNS Layer

It's worth clarifying a distinction that occasionally causes confusion: the 10-lookup ceiling is not a DNS protocol limit at all — DNS itself places no restriction on how many queries a client can issue for a single evaluation task, and there's no DNS-level mechanism that would refuse a domain's eleventh lookup. The limit is entirely an SPF specification-level rule, enforced by whatever SPF evaluation logic is running (inside a mail server's own code, a library, or a validation tool), not by the DNS resolver or DNS servers being queried. This matters practically because it means the limit is only as reliable as the correctness of whatever specific software is doing the enforcing. A poorly implemented SPF library that doesn't correctly track and cap the running lookup count during recursive evaluation could, in principle, exceed the specified ceiling without DNS itself doing anything to stop it, which is exactly why RFC 7208 places the burden of correct enforcement squarely on implementations, and why using well-established, widely-deployed SPF libraries (rather than a custom, less-tested implementation) matters for getting this specific behavior right in production mail systems.

What a Non-Compliant Implementation's Failure Looks Like in Practice

An SPF evaluator that fails to correctly enforce the lookup ceiling doesn't fail loudly or obviously — it simply continues evaluating past where a compliant implementation would have stopped and returned permerror, potentially completing an evaluation that a compliant, RFC-following implementation would have refused to complete. This creates a subtle interoperability problem: a domain's record might appear to work correctly when tested against one specific validation tool, while actually exceeding the ceiling and triggering a permerror at a different, correctly-compliant mail server elsewhere. This is a strong practical argument for testing SPF records against multiple independent, well-regarded validation sources rather than trusting a single tool's result as universally representative of how every receiving mail server will actually behave, since not every implementation in the wild necessarily enforces every rule with identical rigor.

The Relationship Between Lookup Count and DNS Query Timeout Behavior

A related, less commonly discussed consideration: each individual DNS lookup within an SPF evaluation carries its own timeout behavior, and a record with many lookups — even one that stays technically under the 10-lookup ceiling — accumulates more total time spent waiting on DNS responses than a leaner record does. Most of the time this accumulated latency is negligible, measured in milliseconds per lookup under normal DNS conditions. But under degraded network conditions, a slow or partially unresponsive DNS server on the vendor's end, or unusual resolver load on the receiving mail server's side, a record with several includes chained together can produce noticeably slower overall SPF evaluation than a lean record would, in the worst case risking a timeout on the SPF check itself before all lookups complete. This is a secondary, performance-oriented reason (distinct from the hard permerror risk) to keep a record's lookup count comfortably below the ceiling rather than treating "under 10" as the only threshold worth caring about.

Related Reading in This Series

For a deeper look at how a single include mechanism resolves and what makes some vendors heavier than others, see SPF Include Mechanism. If you're specifically weighing whether to flatten your record into static IPs, read SPF Flattening. For the broader set of causes behind a permerror result beyond just the lookup count, see SPF PermError Fix. To check your current record's exact lookup count today, open SPF Lookup.

Reviewed by: ToolsNovaHub Editorial Team📅 Last updated: August 2026📜 Sourced from: RFC 7208

ToolsNovaHub tools are built and independently maintained with a focus on accurate, no-signup network and security utilities. Spotted an error? Let us know.

📋 Related Tools & Guides Comparison

ResourceTypeLink
SPF LookupToolOpen Tool →
SPF Include MechanismGuideRead Guide →
SPF FlatteningGuideRead Guide →
SPF PermError FixGuideRead Guide →
SPF Record OptimizationGuideRead Guide →
Try it yourself — 100% free
🚀 Open SPF Lookup

🔗 More Guides

FAQ

RFC 7208 fixed the number at 10 as a deliberate ceiling on how much DNS work a single SPF evaluation can trigger, protecting the receiving mail server from doing unbounded recursive lookups on every inbound message.
No. The first lookup that retrieves your domain's own SPF TXT record does not count toward the 10. The count only applies to mechanisms inside that record which themselves trigger further DNS lookups.
include, a, mx, ptr, and exists all count as one lookup each time they appear. all, ip4, and ip6 never count, since they don't require a DNS query to evaluate.
The mx mechanism itself counts as one lookup for retrieving the MX records, but each returned MX hostname then needs its own A/AAAA lookup, and RFC 7208 counts those too, so a domain with five MX hosts can consume six lookups from a single mx mechanism.
SPF evaluation stops immediately and returns a permerror. Receiving mail servers are instructed by the RFC to treat a permerror cautiously, and many will reject or heavily penalize the message rather than falling back to a soft result.
It's a hard, unambiguous permerror as defined by the specification, not a soft warning. There's no partial credit for evaluating the first 10 lookups correctly if an 11th mechanism triggers.
Yes. ip4 and ip6 mechanisms specify literal address ranges directly in the record and require zero DNS lookups to evaluate, so you can add as many as you need without affecting the count.
Yes, and this is the single most common cause of accidental limit breaches. Each include triggers a lookup for its own TXT record, and if that record itself contains more includes, those are evaluated recursively and counted too.
Yes, it's a distinct sub-limit of 2. A void lookup is any DNS query that returns no answer at all (NXDOMAIN or empty), and RFC 7208 caps a domain's SPF evaluation to at most 2 such void lookups before also returning a permerror, independent of the main count of 10.
Yes, ptr still counts as a lookup mechanism under RFC 7208 even though the specification explicitly discourages its use due to cost, unreliability, and reverse DNS dependency.
Very easily. Some vendor SPF includes resolve through two or three additional layers of nested includes internally, so a single third-party include can silently consume four, five, or more of your 10 available lookups.
Walk through the record left to right and tally every include, a, mx, ptr, and exists mechanism, remembering that mx and ptr mechanisms can each expand into additional per-hostname lookups depending on DNS answers.
Yes, directly and immediately. Every abandoned vendor include still consumes lookup budget on every single inbound mail evaluation, whether or not you still send mail through that vendor.
It's one valid fix, but it trades lookup-safety for a maintenance burden, since flattened IPs need to be re-synced whenever the underlying vendor's sending ranges change. For records close to but under the limit, trimming unused includes is usually the lower-risk fix.
It applies per single SPF evaluation of one sender's return-path domain for one message, not cumulatively across a mail session or across multiple messages.
Most major providers enforce it per RFC 7208, but there is some variance in how strictly a permerror result affects deliverability decisions, since the RFC leaves the exact disposition of a permerror up to the receiver's local policy.