CertaDNS
Skip to lesson

The Lookup Budget · lesson 1 of 3

Counting, with the working shown

After this lesson you can

Produce a defensible lookup count for any record, including every nested include.

Assumes you have read The algorithm, term by term.

"About eight, I think" is not an audit. This lesson is a procedure that produces a number you can show someone, with the working attached, so a disagreement about whether a record is safe can be settled rather than argued.

What spends from the budget

TermCostNote
include1 + the entire cost of the target recordRecursive. This is where budgets disappear.
a1With or without an argument.
mx1 + one per MX host returnedThe next lesson is entirely about this.
ptr1 + moreDeprecated. Treat any occurrence as a finding.
exists1Regardless of how many hosts it can authorise.
redirect=1 + the cost of the targetReplaces rather than adds, but still spends.
ip4, ip6, all0Free. Literal ranges never query anything.

The initial fetch of the record itself is not counted (RFC 7208 §4.6.4), which is the most common off-by-one in a manual count.

The procedure

1. Fetch the record.
2. List every lookup-costing term, in order. Note the running total.
3. For each include or redirect target:
     fetch it, repeat from step 2, add its total to yours.
4. For each mx: resolve the MX set, count the hosts, add one per host.
5. Stop the moment the running total exceeds 10 — that is a permerror
   and nothing after it matters.
6. Record the tree, not just the number. The number without the tree
   cannot be re-checked by anyone else.

A worked audit

github.com, checked 2026-09-15. Top level first:

$ dig +short TXT github.com | grep spf1
v=spf1 ip4:192.30.252.0/22
       include:spf.protection.outlook.com      1
       include:_netblocks.google.com           2
       include:_netblocks2.google.com          3
       include:mail.zendesk.com                4
       include:_spf.salesforce.com             5
       include:servers.mcsv.net                6
       include:mktomail.com                    7
       include:sendgrid.net                    8
       ip4:... ip4:... ip4:... ip4:...         free
       ~all                                    free
Eight at the top level. The ip4 terms cost nothing.

Now open each include and add what it spends:

spf.protection.outlook.com    +0   (ip4/ip6 literals only)
_netblocks.google.com         +0
_netblocks2.google.com        +0
mail.zendesk.com              +0
_spf.salesforce.com           +1   exists:%{i}._spf.mta.salesforce.com
servers.mcsv.net              +0
mktomail.com                  +0
sendgrid.net                  +1   include:ab.sendgrid.net
                              ---
                        TOTAL  10  of 10

Ten of ten is not a passing grade

It means zero headroom. Any one of those eight platforms adding a single include to its own record — which they do, without telling anyone — pushes this domain to permerror and turns SPF off for it entirely. A record at 10 is not healthy; it is one vendor change from broken, and nobody will be notified.

Keep the tree

  • The total alone is unfalsifiable. The tree lets a colleague re-run your count and disagree with a specific line.
  • It shows where the budget went, which is what the remediation conversation needs. "Eight of our ten are third-party platforms" is an argument; "we are at ten" is not.
  • Re-run it on a schedule. The count changes without you editing anything — module 8.

Try it on a real domain

Free, no account, public DNS only.

Go deeper

Last reviewed