All systems operationalReal-time DNS, email and infrastructure monitoring
SupportAPIContactSign in
EMAIL DELIVERABILITY

The SPF 10-Lookup Limit and the Silent PermError

Add one more vendor to your SPF record and mail can start failing for everyone — with no bounce, no error in your sending dashboard and nothing in your logs.

SPF include tree exceeding the 10 DNS lookup limitv=spf1 include:… -all0include:_spf.google.com1include:sendgrid.net2include:spf.protection…3_netblocks.google.com4_netblocks2.google.com5include:… (vendor)6spf-a.outlook.com7spf-b.outlook.com8a:mail.vendor.net9mx10include:legacy-crm.io1111 / 10 lookupsPermError → SPF fails

Somebody in marketing signs up for a new newsletter platform. Support adds a helpdesk that sends from your domain. Finance switches invoicing tools. Each time, the vendor's setup guide says the same thing: "add include:vendor.example to your SPF record." Each time, someone does.

Then one day mail starts landing in spam — not from the new vendor, but from everything. Your main mail platform, your password resets, your invoices. Nothing changed in those systems. What changed is that your SPF record crossed a limit that has existed since 2014, and every receiver now treats it as broken.

The rule

SPF is evaluated by the receiving server, which has to resolve your record in real time while a message is waiting. To stop a single lookup turning into a denial-of-service amplifier, RFC 7208 sets a hard ceiling: evaluating an SPF record may trigger no more than ten DNS-querying mechanisms.

These mechanisms count towards the limit:

CountsDoes not count
include:ip4:
a and a:ip6:
mx and mx:all
ptr (deprecated — remove it)v=spf1
exists:Tags such as exp=
redirect= 

The crucial part is that the count is recursive. Every include: costs one lookup, and then everything inside that vendor's record costs more. A vendor whose record contains three nested includes costs you four, not one.

A second, smaller limit: RFC 7208 also caps "void lookups" — queries that return no record — at two. A record pointing at a vendor domain that no longer exists can therefore break evaluation on its own, well before you reach ten.

How the arithmetic goes wrong

A record like this looks modest. It has five includes, so it feels like five lookups:

v=spf1 include:_spf.google.com include:sendgrid.net include:servers.mcsv.net
       include:mail.zendesk.com include:_spf.salesforce.com ~all

In practice each of those expands. A typical major provider's record contains several nested includes of its own, and one or two vendors adding a mechanism on their side — entirely outside your control — is enough to push the total past ten. You changed nothing; your SPF still broke.

What "PermError" actually does to you

When evaluation exceeds the limit, the receiver does not return "fail". It returns PermError: a permanent error meaning the record could not be evaluated. In practice most receivers treat PermError the same way they treat a domain with no SPF record at all.

That has a knock-on effect. SPF can no longer contribute a pass to DMARC, so the only way a message can satisfy DMARC is an aligned DKIM signature. If DKIM is missing, signed by a vendor's own domain, or broken by a mailing list that modified the message, DMARC fails — and your policy is applied to your own legitimate mail.

What breaks without it

  • Everything degrades at once. The limit is a property of the record, not of one vendor, so the moment it is exceeded every system sending from your domain loses its SPF pass simultaneously.
  • Your dashboards stay green. Vendors report a successful send. The message left their servers; what happened at the receiver is not shown. There is no bounce to investigate.
  • Enforcement turns it into an outage. With p=reject and no aligned DKIM, mail that would otherwise have been filed as spam is now refused outright.
  • It regresses on its own. Because the count includes vendor records, you can pass today and fail next month with no change on your side.
Do not "fix" it by removing all. A record with no all mechanism is treated as neutral — it authorises nobody and protects nothing. The limit problem stays exactly where it was.

How to check it in 30 seconds

Run an SPF Lookup for your domain. It expands every include: and redirect= recursively, shows the full tree, and gives you the running total against the limit of ten — so you can see which vendor is responsible rather than guessing.

Before you publish a change, paste the new record into the SPF Record Validator. It counts the lookups of a record that does not exist in DNS yet, which is the only safe way to test an edit to a live domain.

Fix it

Work through these in order — the first two solve most cases:
  • Remove what you no longer use. Old newsletter tools, a former helpdesk, a migrated mail platform. Dead includes are the most common cause and the safest thing to delete.
  • Remove ptr entirely. It is deprecated by RFC 7208, slow, and costs a lookup.
  • Drop redundant mechanisms. If your mail servers are already covered by a vendor's include:, the extra a and mx are two lookups you are paying for twice.
  • Move bulk mail to a subdomain. Send marketing from news.example.com with its own SPF record and its own ten-lookup budget. This is the structural fix: your transactional mail stops competing with campaign tooling for space.
  • Flatten only as a last resort. Replacing an include: with the vendor's literal ip4: ranges removes lookups, but freezes a list that the vendor may change without telling you. If you flatten, re-check the source record on a schedule.
  • Publish exactly one SPF record. Two v=spf1 records on the same name is a permanent error regardless of the lookup count.

Once the count is back under ten, make sure DKIM is signing with your own domain so that SPF is not the only thing standing between you and a DMARC failure. That relationship is covered in how a receiver actually decides.

Then keep it that way

An SPF record is one of the few pieces of your infrastructure that can break without anyone touching it, because part of it is maintained by other companies. A quarterly manual check will not catch a vendor that adds an include the week after you looked.

StatusDNS re-checks your SPF record on a schedule, expands it in full, counts the lookups the way a receiver does, and alerts you by email, Slack or webhook when the record changes or the count crosses the limit. If you are about to move to an enforcing DMARC policy, read the staged rollout plan first.

Monitor it instead of remembering it. StatusDNS re-checks this automatically and emails you when it changes. Start a free month — no card needed.

Keep reading

MTA-STS policy enforcing TLS between mail serversSending servergmail.comYour MXmail.example.com_mta-sts TXTv=STSv1; id=20260901https://mta-sts.example.commode: enforce · mx: mail.example.comSTARTTLS · valid certificate · TLS 1.2+Downgrade attempt → refused, reported via TLS-RPT
Email deliverability11 min

Making SMTP Encryption Something You Can Rely On

STARTTLS is optional by design, and anyone in the network path can remove the offer. MTA-STS and TLS-RPT turn "we probably used TLS" into something you can require and verify.

Bulk sender requirements checklistBulk sender requirements — Gmail · Yahoo · MicrosoftSPF and DKIM on every sending domainDMARC record (p=none is enough to start)From domain aligned with SPF or DKIMValid forward and reverse DNS (PTR)TLS on every connection!One-click List-Unsubscribe (RFC 8058)!Spam rate below 0.3 % in Postmaster Tools
Email deliverability10 min

The Bulk Sender Checklist for Gmail, Yahoo and Microsoft

Since February 2024 the large mailbox providers stopped treating authentication as optional. Here is the full checklist and what happens when you miss an item.

DMARC rollout timeline from none to rejectp=noneWeek 0–4Collect reports, fix sendersReports: mostly failquarantinepct=25Small share to spamReports: improvingquarantinepct=100All failures to spamReports: ≥ 98% passp=rejectEnforcedSpoofed mail rejectedReports: stableOnly move to the next stage when aggregate reports show your legitimate senders alignedv=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc@yourdomain.com; adkim=r; aspf=r
Email deliverability11 min

From p=none to p=reject Without Breaking Your Mail

Publishing an enforcing policy on day one is how legitimate mail disappears. Here is the staged path, plus what to do about forwarding and mailing lists.