Why the limit exists
RFC 7208 caps evaluation of an SPF record at 10 DNS-querying mechanisms. Without that bound a single record could trigger hundreds of queries at every receiver through nested include: chains — a convenient amplifier for denial-of-service attacks.
Counted are a, mx, ptr, exists, include and redirect. Not counted are ip4: and ip6: — they need no query.
The misconception: the budget is recursive
Counting does not stop at your record. Every include: is resolved, and whatever mechanisms live there count too — across any number of levels. Three visible includes can easily add up to twelve actual lookups:
This is why counting the entries in your own record does not help. You need the total across the whole chain — and that total changes when a provider extends their record, with no action on your side.
Trimming without losing senders
- Remove unused includes. Almost every grown record carries a service that stopped sending years ago. Cheapest win available.
- Replace
aandmx. Both cost one lookup each and often resolve to fixed addresses. Written asip4:they cost nothing. - Inline small includes. If a provider only has two fixed IPs, replace the
include:with those IPs. Caveat: you then maintain them yourself and must track the provider's changes. - Subdomains for bulk sending. The cleanest route with many vendors: send newsletters from
news.yourdomain.comwith its own SPF record. Every subdomain gets its own budget of 10. - Drop
ptrentirely. The mechanism is slow, unreliable and explicitly discouraged by RFC 7208.
What does not work
A second SPF record for the same domain is not a solution but another permerror: exactly one v=spf1 record per domain is permitted. Nor does redirect= route around anything — it counts as a lookup as well.