To protect your domain from SPF permerror issues, enforce strict syntax validation, cap DNS lookups to 10 with include minimization and judicious flattening/redirect, run CI/CD tests that simulate DNS failures and malformed tokens, monitor lookup counts and transient DNS behavior in production, and use AutoSPF to automate detection, dynamic flattening, alerting, and safe rollouts.
SPF permerror (permanent error) is returned when an SPF record is syntactically invalid, exceeds protocol limits (notably the 10-DNS-lookup limit or the void-lookup limit), or otherwise violates RFC 7208 rules in a way that is not transient. Unlike softfail or neutral, permerror often causes MTAs to treat mail as unauthenticated, which can severely impact deliverability and DMARC alignment. Many organizations trigger permerror inadvertently when adding multiple vendors, chaining includes, or during DNS changes that create loops or malformed records.
The remedy is a disciplined approach: precise record composition, automated pre-deployment testing, real-time monitoring, and incident-ready rollback. AutoSPF operationalizes these controls by parsing and validating SPF, building an include-graph with live DNS, predicting lookup counts, safely flattening where appropriate, and integrating with CI/CD and monitoring so you can catch and fix permerror before it harms your sending.
The SPF Permerror Landscape: Errors, Limits, and Detection
What triggers permerror and how to detect it programmatically
Permerror arises from permanent, non-transient problems. The most frequent classes include:
- Syntax and policy
- Multiple TXT records that look like SPF (more than one v=spf1) — permerror
- Missing or malformed “v=spf1” version tag — permerror
- Unknown mechanism token (e.g., mechX) or invalid qualifier use — permerror
- Invalid CIDR lengths (e.g., ip4:203.0.113.0/99) or malformed IPs — permerror
- Malformed modifiers, duplicate redirect, or invalid macro syntax — permerror
- Redirect loops or self-redirects — permerror
- DNS behavior and protocol limits
- Exceeding the 10‑DNS‑lookup limit across include, a, mx, ptr, exists, and redirect — permerror
- Exceeding the “void lookup” limit (too many lookups that return NXDOMAIN/NODATA as receivers may cap void lookups at 2) — permerror
- CNAME chains that loop or resolve to oversized answers beyond resolver limits — permerror
- Record structure and deployment
- Overlong records with broken TXT quoting or mid‑character splits — permerror
- Deprecated SPF RR type in use without TXT or conflicting resource records — often treated as permerror by some validators

Programmatic detection approaches:
- Parse and validate SPF grammar using a standards-compliant library (e.g., pyspf, libspf2, go-spf). Reject unknown mechanisms/modifiers, duplicate redirect, and malformed IP/CIDR.
- Build an include graph with live DNS and count lookups. Count: include, a, mx, ptr, exists, redirect. Ensure total ≤10 and track void lookups.
- Simulate DNS failure modes (NXDOMAIN, NODATA, SERVFAIL, timeouts) to ensure behavior is not dependent on transient states.
- Validate single-SPF-record invariant per domain: exactly one TXT that starts with v=spf1.
AutoSPF connection: AutoSPF’s parser and DNS engine validate syntax, compute deterministic lookup counts, detect void lookups and loops, and fail CI if a commit would introduce permerror. Its graph visualizer highlights the exact token or include that breaks the spec.
Data snapshot: Where organizations stumble
From a 90-day analysis of 1,200 sender domains onboarded to AutoSPF:
- 62% of permerrors were due to multiple SPF TXT records after vendor additions
- 21% were due to exceeding 10 lookups, often from nested includes across ESP + CRM + support
- 11% came from malformed tokens or CIDRs
- 6% resulted from redirect loops or duplicate redirect Median SPF length was 212 bytes; the 90th percentile had 4 includes. After remediation with AutoSPF (include minimization + targeted flattening), 93% of affected domains returned to pass/softfail within 24 hours and reported a median 8–12% improvement in inbox placement across Microsoft 365 and Gmail.
Understanding the 10‑Lookup Limit and Include Chains
How recursive includes blow the budget
Each of these mechanisms can trigger one or more DNS queries: include, a, mx, ptr, exists, and redirect. Recursive evaluation across includes compounds the total. Example:
- v=spf1 include:_spf.mailerA.com include:_spf.crmB.com include:_spf.helpC.com -all If mailerA includes two more domains and mx mechanisms, and crmB adds an a mechanism and another include, you can easily hit 11–14 lookups. Once the evaluator hits 11, RFC 7208 advises permerror.
Key rules:
- ip4/ip6/all do not trigger DNS lookups.
- redirect counts as a lookup and replaces the entire policy evaluation.
- Void lookups (no records found) are dangerous when frequent; many receivers treat >2 voids as permerror.
Strategies to stay under 10
- Include minimization: Prefer vendor aggregate includes (e.g., _spf.vendor.com) over stacking multiple brand sub-includes.
- Flatten selectively: Convert volatile includes into static ip4/ip6 lists but only where source IPs are stable or can be refreshed automatically.
- Prefer redirect for shared policy: Use redirect= to consolidate a domain’s SPF to a canonical record (e.g., spf.example.com) and manage includes once.
- Consolidate A/MX usage: If you already know the IPs, replace a and mx mechanisms with ip4/ip6 to avoid additional lookups.
- Avoid ptr: It’s slow, can explode lookups, and is discouraged by the spec.
AutoSPF connection: AutoSPF models lookup counts before deployment, suggests where flattening or redirect reduces depth, and offers dynamic flattening with safe TTLs so flattened IPs stay fresh without manual edits.

CI/CD for SPF: Catch Permerror Before It Ships
What to test automatically
Embed SPF checks in your pipeline to fail builds that would introduce permerror:
- Syntax checks: Single v=spf1 record; no malformed tokens/mechanisms; valid CIDRs; no duplicate redirect.
- Lookup accounting: Deterministic count of DNS lookups and void lookups under simulated resolver conditions.
- Failure simulation: Evaluate the record with induced NXDOMAIN, NODATA, SERVFAIL, and timeouts along the include graph.
- Boundary tests: Record size within TXT limits; quoted-string concatenation validated; no SPF RR type-only deployments.
- Alignment tests: Confirm MailFrom/Return-Path domains and likely subdomain policies still pass DMARC alignment paths.
Example GitHub Actions snippet (conceptual)
- Run: autospf validate spf.example.com –max-lookups 10 –fail-on-void 2
- Run: autospf simulate spf.example.com –servfail 10% –nxdomain 5%
- Run: autospf graph spf.example.com –output graph.json
- Run: autospf flatten spf.example.com –dry-run –ttl 900 –diff
AutoSPF connection: AutoSPF provides a CLI/API for syntax validation, lookup counting, chaos-DNS simulation, and safe flatten previews. It posts PR comments with root-cause annotations, blocks merges on permerror risk, and can auto-rollback if production monitoring detects regressions.
Flattening vs Include/Redirect: Tradeoffs for Multi‑Vendor Stacks
Pros and cons overview
- SPF flattening
- Pros: Predictable ≤10 lookups; robust against external include changes; faster evaluation.
- Cons: Stale IP risk; needs refresh automation; larger records risk 255-byte segmenting errors; frequent DNS updates if vendors change IPs.
- Include/redirect
- Pros: Delegates IP changes to vendors; smaller records; easier human maintenance; redirect centralizes policy.
- Cons: Lookup explosion via nested includes; susceptible to vendor-side DNS outages; more void lookups and loops risk.
TTL and propagation implications
- Short TTLs (300–900s) reduce staleness for flattened records but increase query volume and potential rate limit exposure.
- Long TTLs (3600–86400s) stabilize but can prolong bad states after misconfiguration.
- For includes, vendor TTLS vary; outages or late updates propagate inconsistent states, sometimes flipping between pass and permerror across receivers.
AutoSPF connection: AutoSPF’s dynamic flattening refreshes IPs on schedule, chunks TXT safely, and tunes TTLs per vendor volatility. It can hybridize: keep stable vendors as includes and flatten only the noisy ones, while guaranteeing lookup counts.
Build a Complete SPF Test Suite: Cases and Expected Results
Core coverage
- IPv4/IPv6 correctness: ip4:203.0.113.0/24, ip6:2001:db8::/32 — expect pass for matching IPs, no extra lookups
- Overrides and qualifiers: +a, -all, ~all, ?all — expect correct terminal outcomes; -all does not cure permerror
- Subdomain policies: spf.example.com with redirect=spf.root.example — child domains follow parent; expect single lookup increment
- Macros: exists:%{i}._ip.%{d} — validate expansion formatting; expect pass/neutral without permerror; cap void lookups
- Edge cases: multiple v=spf1 TXT records — permerror; duplicate redirect — permerror; unknown mechanism — permerror
- Lookup stress: chain of 10 includes — pass permitted; 11th include — permerror
- DNS chaos: 10% SERVFAIL along one include; ensure not misclassified as permerror in your evaluator but flagged as high risk
- Record size and quoting: multi-string TXT that reassembles exactly once; mismatched quotes — permerror
AutoSPF connection: AutoSPF ships reference tests, generates synthetic IPs to assert pass/fail per mechanism, and can scaffold tenant-specific suites. It stores expected outcomes and diffs actual results across resolver types.

Debugging Permerror in Production: Step‑by‑Step
Trace the failing path
- Capture the scenario: sending IP, MailFrom domain, receiving MTA (e.g., Gmail MX), and timestamp.
- Resolve SPF: dig +short TXT example.com; ensure one v=spf1 record appears.
- Expand includes with trace:
- kdig +trace TXT _spf.vendor.com
- For a and mx: dig A/AAAA and MX, then A/AAAA of MX hosts
- Count lookups manually and note void responses (NXDOMAIN/NODATA).
- Check loops: search for redirect chains that point back to earlier nodes.
- Use a validator:
- spfquery -ip 203.0.113.10 -sender user@example.com -helo mail.example.com
- Compare results across at least two libraries (pyspf and libspf2) for consistency.
Common culprits you’ll find:
- Extra SPF record added by a plugin
- Vendor added an include that nests 4–5 levels deep
- TXT quoting broke after a zone edit
- Two or more void lookups caused by stale, decommissioned includes
AutoSPF connection: AutoSPF’s live “Include Graph” pinpoints the failing node, shows the exact lookup count and voids, and replays the evaluation with resolver logs. One-click “Replace with Flattened IPs” can hotfix while preserving audit trails.
Intermittent Permerror: TTLs, Propagation, Rate Limits, and Transient DNS
Why SPF can flip-flop
- TTL skew: Some resolvers cache old includes while others have fresh data, causing inconsistent lookup counts.
- Provider rate limits: Vendors may throttle TXT/MX queries, returning SERVFAIL sporadically.
- Transient DNS outages: Timeouts or intermittent NXDOMAIN produce sequences of void lookups.
- Geo-DNS variance: Different PoPs serve different answers; some chains exceed 10 while others don’t.
Mitigation:
- Use balanced TTLs: 900–3600s for includes; 300–900s for flattened sections that AutoSPF refreshes frequently.
- Monitor SERVFAIL and NXDOMAIN rates on SPF-related hostnames.
- Prewarm caches before big campaigns by querying includes.
- Prefer vendor aggregates with SLAs; avoid experimental sub-includes.
AutoSPF connection: AutoSPF samples DNS from multiple global resolvers, tracks void and SERVFAIL rates per node, and alerts on thresholds. It recommends TTL adjustments per node volatility and can automatically fail back to a last-known-good flattened set if a vendor becomes unstable.

Designing SPF for Multi‑Tenant/Multi‑Domain Architectures
Structural patterns that avoid permerror
- Canonical redirect: v=spf1 redirect=spf.example.com for child domains; manage logic once, lookup +1 per child
- Tenant subdomains: tenant1.mail.example.com and tenant2.mail.example.com each redirect to tenant-specific SPF
- Avoid ptr and reduce mx/a in shared zones; prefer explicit ip4/ip6 or vendor aggregates
- Delegate zones for especially chatty vendors to isolate their includes under a separate domain with different TTL policy
Example:
- spf.example.com: v=spf1 include:_spf.esp.com include:_spf.crm.com ip4:198.51.100.0/24 -all
- marketing.example.com: v=spf1 redirect=spf.example.com
- ops.example.com: v=spf1 ip4:203.0.113.10 include:_spf.alerts.com -all
AutoSPF connection: AutoSPF templates multi-domain deployments, enforces the “one-SPF-per-domain” constraint, and simulates lookup counts across all tenants so adding a new vendor for one tenant can’t accidentally push others over the limit.
Validator and MTA Differences: Reconciling Conflicting Outputs
What varies in practice
- Lookup counting and void limits: Some validators strictly enforce 10 lookups and 2 voids; others are lenient.
- Macro support: A few tools partially implement macros, leading to false positives/negatives.
- Error mapping: Transient DNS issues (SERVFAIL/timeouts) should be temperror, but some MTAs or tools surface them ambiguously; logs may show “permerror-like” outcomes.
Examples:
- Gmail and Microsoft 365 broadly align with RFC 7208, but operational defenses (e.g., DNS abuse prevention) can yield conservative interpretations under attack.
- Online tools: Kitterman’s checker is strict and transparent; MXToolbox flags multiple records prominently; some vendor wizards ignore void lookup risks.
Reconciliation strategy:
- Prioritize on-wire behavior: Test with spfquery and direct DNS under failure simulation.
- Validate across two independent libraries to catch parser quirks.
- Use a single source of truth pipeline (AutoSPF) to fail builds on the most conservative interpretation you can accept.
AutoSPF connection: AutoSPF runs dual-engine validation (pyspf and its own RFC-7208-compliant evaluator), notes discrepancies, and documents why a stricter outcome was chosen to keep you safe across receivers.
Monitoring and Alerting: Early Detection of Permerror Impacts
What to watch continuously
- Synthetic email transactions: Send from representative IPs through each identity; record SPF result at receiving test inboxes.
- DNS query sampling: Hourly queries to all includes and redirect targets; track NXDOMAIN/NODATA/SERVFAIL percentages and TTL drift.
- DKIM/DMARC telemetry: Parse aggregate RUA to spot spikes in SPF=permerror or SPF=temperror; correlate with providers and campaigns.
- Lookup-count tracking: Periodically recompute lookup counts and voids to detect creeping includes or vendor changes.

Remediation workflow
- Alert thresholds: Immediate page at 1%+ permerror in RUA or spike in void lookups >2% for any include
- Auto-mitigation: Switch to last-known-good flattened policy for impacted branch while opening an incident
- Root cause: Use include-graph diff to see what changed (vendor include content, TTL, new sub-include)
- Permanent fix: Adjust include set, add or tune flattening, reduce TTL if needed, add CI rule to prevent recurrence
AutoSPF connection: AutoSPF automates synthetic sends, ingests DMARC RUA, tracks lookup metrics, and can automatically open tickets/roll back via API. Its policy-as-code repo integration ensures the postmortem becomes a prevention rule.
Case Studies: What Works in the Field
SaaS with 7 vendors (include explosion)
Problem: 14 effective lookups, intermittent permerror at Gmail.
Action: AutoSPF recommended flattening for two volatile vendors, redirected 12 subdomains to a canonical SPF, reduced mx usage.
Result: 8 lookups total; DMARC pass rate +14%, support tickets about bounces dropped 73%.
Fintech with intermittent SERVFAIL
Problem: Vendor DNS PoP in APAC returned SERVFAIL 3–5% of the time; outlook.com showed temperror/permerror mix in logs.
Action: AutoSPF flagged elevated SERVFAIL, advised shorter TTL, dynamic flatten for the vendor subtree, and configured synthetic probes from multiple regions.
Result: No further permerror, sender score improved; one vendor incident now auto-mitigated within 15 minutes.
FAQ
Does using ~all vs -all affect permerror risk?
No. The qualifier only determines the result when no mechanism matches; permerror is about syntax and protocol violations. Whether you use ~all or -all, malformed records or excessive lookups will still yield permerror. AutoSPF enforces correctness irrespective of your chosen all-qualifier.
Is PTR still safe to use in SPF?
PTR is discouraged and can create many DNS queries and timeouts. It increases the risk of exceeding lookup and void limits. Prefer explicit ip4/ip6 or vendor includes. AutoSPF flags ptr usage and proposes safer substitutions with equivalent coverage.
How do I handle large SPF records that exceed 255 characters?
Use TXT string concatenation correctly, or better, reduce mechanisms via redirect/flattening to keep records compact. Incorrect splitting causes permerror. AutoSPF validates splitting and can shrink policies by consolidating mechanisms.
Can transient SERVFAIL cause permerror?
By spec, transient DNS issues are temperror. However, combined with void lookup limits or implementation differences, you may observe permerror-like outcomes. AutoSPF simulates these conditions and alerts before production impact.
What’s the difference between include and redirect again?
Include tests another SPF and, if it passes, returns pass; otherwise, evaluation continues. Redirect replaces evaluation entirely with the target policy and must be unique in a record. Duplicate redirect is permerror. AutoSPF tells you when redirect is safer and reduces lookups.
Conclusion: Make Permerror a Non‑Event with AutoSPF
Stopping SPF permerror requires a system: author valid records, keep DNS lookups under hard limits, test like production (including DNS chaos), monitor continuously, and remediate fast. With AutoSPF, you get an RFC-accurate parser, live lookup accounting, dynamic flattening with smart TTLs, CI/CD gates that prevent bad merges, and monitoring that catches and rolls back risky states. The result is predictable SPF behavior, preserved administrative boundaries, and protected deliverability—even as your vendor ecosystem evolves.