Skip to content

SPF Record Too Many DNS Lookups — How to Fix

The SPF 10 DNS Lookup Limit

RFC 7208 Section 4.6.4 imposes a hard limit of 10 DNS-querying mechanisms during SPF evaluation. This limit exists to prevent SPF from being abused as a DNS amplification vector — without it, a single SPF check could trigger hundreds of recursive DNS queries.

When a receiving server evaluates your SPF record and the lookup count exceeds 10, the result is a permerror (permanent error). Most receivers treat a permerror the same as an SPF fail — your message loses SPF authentication, which can cause DMARC failures and delivery problems.

This limit is easy to hit. A typical organization using Google Workspace, a marketing platform, and a transactional email service can reach 8-12 lookups from just three include statements, because each include recursively resolves its own includes.

How to Count Your DNS Lookups

What Counts

MechanismLookupsNotes
include1 + nestedThe include itself is 1 lookup, plus all lookups in the included record
a1Resolves A/AAAA records for the specified domain
mx1 + 1 per MX1 for the MX query, then 1 A/AAAA query per MX host (up to 10 MX records)
redirect1 + nestedLike include but replaces the entire evaluation
exists1Checks if an A record exists

What Does Not Count

MechanismLookupsWhy
ip40Direct IP comparison, no DNS query needed
ip60Direct IP comparison, no DNS query needed
all0Matches everything, no DNS query needed

Counting Example

Consider this SPF record:

v=spf1 include:_spf.google.com include:sendgrid.net include:spf.protection.outlook.com mx -all

Lookup count:

  • include:_spf.google.com → 1 (include) + 3 (Google's nested includes: _netblocks.google.com, _netblocks2.google.com, _netblocks3.google.com) = 4
  • include:sendgrid.net → 1 (include) + 1 (sendgrid.net's own include) = 2
  • include:spf.protection.outlook.com → 1 (include) + 2 (Microsoft's nested includes) = 3
  • mx → 1 (MX query) + 2 (A queries for 2 MX hosts) = 3

Total: 12 lookups — exceeds the limit by 2. This record will cause a permerror.

Diagnosing the Problem

Before fixing, you need to know your current lookup count and which mechanisms are consuming them.

Using Our SPF Flatten Tool

Our SPF Flatten tool resolves your entire SPF record tree and shows the total lookup count, all resolved IPs, and any errors. Enter your domain and it will show exactly where your lookups are going.

Manual DNS Inspection

You can trace the lookup chain manually:

# Get your SPF record
dig TXT example.com +short

# Follow each include
dig TXT _spf.google.com +short
dig TXT _netblocks.google.com +short
# ... continue for each nested include

Count each dig query that resolves an include, a, mx, redirect, or exists mechanism. The total must be ≤ 10.

Fix 1: SPF Flattening

SPF flattening replaces include mechanisms with the actual IP addresses they resolve to. This converts DNS-querying mechanisms into ip4/ip6 mechanisms that do not count toward the limit.

Before Flattening

v=spf1 include:_spf.google.com include:sendgrid.net -all

Lookups: 6 (Google 4 + SendGrid 2)

After Flattening

v=spf1 ip4:209.85.128.0/17 ip4:74.125.0.0/16 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:142.250.0.0/15 ip4:167.89.0.0/17 ip4:159.183.0.0/16 -all

Lookups: 0

Trade-offs

  • Pro: Eliminates all DNS lookups from flattened includes
  • Con: Maintenance burden — Service providers change their IP ranges. If Google adds new IPs and your flattened record does not include them, mail from those IPs will fail SPF.
  • Con: Record length — Flattened records can exceed the 255-byte TXT string limit or even the 512-byte UDP DNS response limit. You may need to split into multiple TXT strings or use multiple SPF records via include to a subdomain.

Partial Flattening

You do not have to flatten everything. Flatten the services with stable IPs (your own servers) and keep include for services with frequently changing IPs:

v=spf1 ip4:203.0.113.0/24 include:_spf.google.com -all

This uses 4 lookups (Google) instead of 6+, leaving room for other services.

Fix 2: Reduce Includes

Before flattening, audit whether you actually need all your includes.

Audit Your Sending Sources

  1. Review DMARC aggregate reports — They show which IPs are actually sending email as your domain. If a service is in your SPF record but never appears in reports, you may not need it.
  2. Check each service — Is the marketing platform from 3 years ago still active? Did you switch CRM providers but forget to remove the old include?
  3. Consolidate services — If you use both SendGrid and Mailgun, consider consolidating to one provider.

Use Subdomains

Move different sending services to subdomains. Each subdomain has its own SPF record with its own 10-lookup limit:

  • example.com — Your main domain (transactional email only)
  • mail.example.com — Marketing email via SendGrid
  • support.example.com — Support tickets via Zendesk

Each subdomain gets its own SPF record, and the 10-lookup limit applies independently to each. Configure each service to use its designated subdomain as the envelope sender.

Note: For DMARC alignment, the subdomain approach works with relaxed alignment (default) because mail.example.com aligns with example.com. With strict alignment, the From: header must exactly match the envelope sender domain.

Fix 3: SPF Macros

SPF macros (RFC 7208 Section 7) allow dynamic SPF evaluation using variables like the sender's IP address. This is an advanced technique used by large organizations to work around the lookup limit.

How It Works

Instead of listing all authorized IPs, you create a DNS infrastructure that answers "is this IP authorized?" for each query:

v=spf1 exists:%{i}.spf.example.com -all

The %{i} macro expands to the connecting IP address. The receiver queries 203.0.113.5.spf.example.com — if an A record exists, the IP is authorized. This uses only 1 lookup regardless of how many IPs you authorize.

Setting Up Macro-Based SPF

You need to create A records for each authorized IP:

203.0.113.5.spf.example.com A 127.0.0.1
203.0.113.6.spf.example.com A 127.0.0.1
# ... one record per authorized IP

The A record value does not matter (127.0.0.1 is conventional) — only its existence is checked.

Trade-offs

  • Pro: Only 1 DNS lookup regardless of the number of authorized IPs
  • Con: Complex DNS management — you need to maintain individual A records for every authorized IP
  • Con: Not all receivers fully support SPF macros (though major providers do)
  • Con: Harder to audit — you cannot see all authorized IPs by reading the SPF record

SPF macros are best suited for organizations with hundreds of sending IPs where flattening would create an unmanageably long record.

FAQ

Does the void lookup limit (2) also apply?

Yes. RFC 7208 Section 4.6.4 also limits void lookups (DNS queries that return no records) to 2. Exceeding this limit also causes a permerror. Void lookups typically occur from include mechanisms pointing to domains without SPF records, or a/mx mechanisms for domains without A/MX records.

What about nested includes?

Nested includes count toward the same 10-lookup limit. If your record includes _spf.google.com, and Google's record includes other domains, all those lookups count against your limit. This is why services like Google Workspace can consume 3-4 lookups from a single include.

How often should I re-flatten my SPF record?

Check monthly at minimum. Email service providers change their sending IPs regularly. If you flatten and a provider adds new IPs, mail from those IPs will fail SPF. Some organizations automate flattening with cron jobs that re-resolve and update DNS records daily.

Flatten Your SPF Record

See your current DNS lookup count and get a flattened SPF record instantly.

SPF Flatten Tool → SPF Generator →