Domain Health · SPF · Lookup limit

SPF "too many DNS lookups": a worked fix

Over 10 lookups and SPF returns permerror for every message, including your real ones. Here's one record counted line by line, then cut to 7 with no flattening and no new service.

Try an example:

What counts

  • Cost one lookup each: include, a, mx, ptr, exists and redirect.
  • Nested records count too. Each include costs one, plus every lookup inside the record it points to, and so on down.
  • Free: ip4, ip6 and all.
  • Void lookups: an include or a that finds no record at all. More than 2 of those is also a permerror (RFC 7208, section 4.6.4). A tool you cancelled years ago often leaves one behind.

A worked example

A small business with hosted mail, a CRM, a newsletter tool and a help desk. All names are examples:

example.com TXT "v=spf1 a mx include:_spf.mailhost.example include:spf.crm.example include:send.newsletter.example include:mail.helpdesk.example ~all"

TermLookupsWhy
a1Looks up example.com's own address
mx1Looks up example.com's MX hosts
include:_spf.mailhost.example41, plus 3 nested includes inside it
include:spf.crm.example21, plus 1 nested include
include:send.newsletter.example1Only ip4 ranges inside
include:mail.helpdesk.example21, plus 1 nested include
Total11One over: permerror

The checker above follows every include and shows this count for your real record. Providers change their nested records, so a record that counted 9 last year can count 11 today without you touching it.

Fixes, safest first

1. Remove includes for tools you no longer use (−2 here)

The help desk was replaced last spring. Its include stayed. Delete it. Ask whoever set up each tool before removing anything you don't recognise.

2. Remove a and mx if those hosts don't send (−2 here)

a authorises your website's server; mx authorises the servers that receive your mail. With hosted mail, outgoing mail leaves through the provider's servers, which include:_spf.mailhost.example already covers. Unless your web server sends mail itself (a contact form sending directly, for example), both terms are dead weight. If the web server does send, list its fixed address with ip4: instead, which costs nothing.

3. Check whether a tool needs your SPF record at all

SPF is checked against the message's Return-Path (bounce) domain, not the From domain. Send yourself a test from each tool and read the Return-Path header. If it's the tool's own domain, or a subdomain you set up for it such as bounces.example.com, the include on your root record is never used for that tool's mail: remove it, and make sure the tool signs DKIM with your domain so DMARC still passes (how alignment works). Many newsletter and CRM tools work this way.

4. Only then: flatten, carefully

"Flattening" swaps an include for the IP ranges it currently contains. It works until the provider changes its ranges, then mail from the new ranges fails SPF without warning. Use it only for IPs you control, or with a process that re-checks the ranges regularly.

After the fix

example.com TXT "v=spf1 include:_spf.mailhost.example include:spf.crm.example include:send.newsletter.example ~all"

4 + 2 + 1 = 7 lookups, with room for one more tool later. Run the checker again once the change has published (usually minutes, up to your record's TTL), and send a test from each remaining tool.

Quick reference

  • Limit: 10 lookups including nested ones, and at most 2 that find nothing.
  • ip4, ip6 and all are free; a and mx are not.
  • Remove dead tools first, then a/mx, then includes the Return-Path shows aren't used. Flatten last.
  • Exactly one SPF record per name; two records is its own permerror.

Related: SPF checker · SPF on a CNAME'd name · DMARC checker · Pre-holiday sending check