Skip to content

SPF flattening

Every mechanism that triggers a DNS resolution counts towards the 10-lookup limit:

  • include: (resolves domain and counts nested lookups recursively)
  • a and mx (triggers DNS queries for records)
  • ptr (deprecated and expensive)
  • redirect (resolves target SPF record)

Mechanisms like ip4, ip6, and all do not trigger additional lookups.

Enterprise domains frequently stack multiple SaaS sending vendors over time:

v=spf1 include:_spf.google.com include:sendgrid.net include:mailgun.org include:salesforce.com ~all

When each vendor includes multiple nested domains, the lookup count easily hits 12–16 lookups, producing silent delivery failures and quarantine drops.


SPF flattening replaces dynamic include: mechanisms with direct, resolved ip4: and ip6: CIDR blocks:

  1. Recursively traverse all include: and redirect statements in your current record.
  2. Resolve all underlying IP ranges.
  3. Deduplicate and consolidate overlapping CIDRs.
  4. Publish the flattened IP list directly into DNS TXT records.
# Before (Nested Lookups: 12)
v=spf1 include:_spf.google.com include:sendgrid.net ~all
# After Flattening (Lookups: 0-1)
v=spf1 ip4:35.190.247.0/24 ip4:167.89.0.0/17 ip4:198.2.128.0/18 ~all

DNS TXT records have a 255-byte limit per string (and UDP packets historically prefer under 512 bytes). When an organization has dozens of sending IPs, split the record across dedicated sub-records:

v=spf1 include:_spf1.example.com include:_spf2.example.com -all

Because SaaS providers can rotate their IP ranges, manual flattening risks stale records. Implement an automated workflow:

  1. Daily Cron/Scheduled Job: Resolve upstream SaaS provider SPF records.
  2. Diff Detection: Compare new CIDR sets against published DNS records.
  3. Automated Pull Request / DNS API Update: Apply DNS TXT updates via Cloudflare or Route 53 API when changes are detected.
Terminal window
# Verify SPF record lookups and syntax locally
dig +short TXT example.com

  • Evaluated total DNS lookup count using a lookup checker (under 10).
  • Validated RFC 7208 syntax without duplicate mechanisms.
  • Enforced ~all (softfail) during transition, moving to -all (fail) with DMARC alignment.
  • Automated daily verification against upstream SaaS vendor IP changes.