Glossary

    SPF Flattening: The Definition, and What It Trades Away

    The short answer

    SPF flattening rewrites a record's include statements as the IP addresses those lookups return, because RFC 7208 caps lookup-causing terms at ten and returns permerror past it while ip4 and ip6 are exempt. It resolves the count and takes a stored copy of infrastructure somebody else maintains, which then decays without reporting anything.

    Key takeaways

    • RFC 7208 caps include, a, mx, ptr, exists and redirect at ten per evaluation and requires permerror past it, while all, ip4 and ip6 are exempt from that count.
    • A permerror stops SPF contributing anything for every sender on the record, leaving DMARC resting on DKIM alone.
    • A flattened record is a snapshot of another company's address ranges, and it goes stale silently as they change.
    • A purpose-built sending domain needs one include, so needing to flatten usually means the record was copied from a primary domain.

    SPF flattening is the practice of replacing the lookup-causing terms in an SPF record, in practice mostly include: statements, with the literal IP addresses those lookups would have returned, so that the record resolves inside the ten-lookup ceiling the specification imposes. The record ends up longer to read and cheaper to evaluate, because a list of addresses costs a receiver nothing to check.

    The technique is a workaround for a hard limit, and the limit is worth stating exactly before the workaround makes sense.

    The limit it exists to dodge

    RFC 7208 names the terms that cost a DNS query during evaluation: the include, a, mx, ptr and exists mechanisms, and the redirect modifier. It then sets the ceiling in one sentence, saying that implementations "MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS", and that exceeding the limit requires the implementation to return a permerror.

    The other terms behave differently, and that difference is the entire mechanism behind flattening. The specification says that all, ip4, ip6 and the exp modifier "do not cause DNS queries at the time of SPF evaluation", and that their use "is not subject to this limit". So a record built from raw addresses can be arbitrarily long in mechanism count and still resolve, while a record with eleven includes cannot resolve at all.

    The counting is recursive, which is what catches people out. Each include: costs one lookup, and then the record it points at is evaluated with its own lookup-causing terms counting against the same budget. A single include pointing at a provider whose own record carries four includes has consumed five, not one, and the provider can change their record without telling you.

    1. Step 1Publish three includes

      One for the mail platform, one for the CRM, one for the invoicing tool. Three lookups on your own record.

    2. Step 2Each one expands

      Every included record is evaluated with its own lookup-causing terms, and those count against the same budget of ten.

    3. Step 3A provider grows

      A vendor adds a region or a sub-provider to their own record. Your count rises and nothing on your domain changed.

    4. Step 4Evaluation stops

      Past ten, the check returns permerror. SPF contributes nothing, for any sender on the record.

    How a record crosses the ceiling without anybody adding a mechanism to it.

    Why it matters

    A permerror is not a soft failure and it is not a warning. It is the evaluation abandoning the check before it reaches any verdict about the sending address, so SPF stops contributing anything at all, for every sender on that record rather than only for the one that pushed it over.

    The consequence lands one layer up. A message passes DMARC when either SPF or DKIM passes and aligns with the visible sender, so a record in permerror has removed half of that redundancy without removing the appearance of having it. Everything then rests on DKIM alone, and a key rotation that would have been survivable takes the domain to zero. That failure is quiet by construction: nothing in a sending platform reports it, the record still looks present in a DNS panel, and the first symptom is placement getting worse for reasons nobody can trace. The other five causes worth ruling out first are in why DMARC is failing.

    So the problem flattening addresses is real and the pain is genuine. The argument is about whether the fix is the right one.

    Where the technique breaks

    Flattening trades a live reference for a stored copy, and everything difficult about it follows from that trade.

    A flattened record is a snapshot of somebody else's infrastructure. The whole point of include: is that the provider maintains the address list and you inherit their changes. Flatten it and you have taken a copy on the day you ran the tool. When the provider adds a sending region, retires a range, or migrates a service, your record still authorises yesterday's addresses and silently fails to authorise today's. The failure appears as SPF failures at some receivers and not others, on mail you did send.

    Nothing tells you it has gone stale. There is no error, no bounce that names the cause, and no expiry on the record. A flattened record decays continuously and reports nothing, which is the same shape as the permerror it was published to fix. The one place the decay does surface is in aggregate reporting, where a source you recognise starts appearing with SPF failures against a domain you thought was configured, which is one of several reasons DMARC aggregate reports are worth turning on before they are needed rather than after.

    The record gets long, and length has its own limits. DNS TXT records are built from strings of at most 255 characters, and a long value has to be split into several quoted strings inside one record. Provider interfaces vary in how they handle that, and a panel that silently wraps or re-quotes a long value produces a record that looks present and never validates.

    Automated flattening moves the problem rather than removing it. Services exist that re-flatten on a schedule and serve the result, usually through a redirect to a record they host, which keeps the addresses current. That is a genuine improvement on a hand-flattened record and it introduces a dependency: your domain's ability to authenticate now runs through a third party's hosted record and their uptime. That may be a reasonable trade for a company with a genuinely complicated mail estate. It is a decision to make deliberately rather than a default.

    Flatten by handA stored copy of the addresses
    • Resolves the lookup count immediately
    • Decays silently as providers change
    • No error when it goes stale
    • Needs a human to re-run it, forever
    • Record grows long enough to hit string limits
    Automated flatteningA hosted record kept current
    • Addresses stay current without hand maintenance
    • Introduces a third-party dependency in the authentication path
    • Usually reached through a redirect to their record
    • Reasonable for a complicated estate
    • A subscription and an uptime question
    Remove sendersFewer includes on the record
    • Fixes the cause rather than the symptom
    • Costs an inventory of who actually sends
    • Free, and stays fixed
    • Not always available on a primary domain
    • The default for a purpose-built sending domain
    The three ways a record over the ceiling gets resolved, and what each one costs.

    How it is used in outbound

    Section illustration: How it is used in outbound

    For an outbound programme the useful conclusion is that flattening should almost never be necessary, and needing it is a signal about the record rather than about the ceiling. The distinction is between a domain that accumulated senders and a domain that was built for one job.

    A primary company domain accumulates a sender every time a department buys software, so it carries a mail platform, a CRM, a helpdesk, a marketing tool and an invoicing service, and it genuinely can approach ten. A purpose-built sending domain carries one platform, so it needs one include and its lookup count stays in single figures for its entire life.

    The failure that produces flattening on an outbound estate is therefore a copy-paste one. Somebody takes the primary domain's record, which was correct for the primary domain, and pastes it onto twenty new sending domains. Every one of them inherits authorisations for services that will never send from it, along with every lookup those includes consume, and the fleet is one vendor expansion away from a permerror it did not need to be exposed to. The lookup arithmetic and how to count your way back under the ceiling is in SPF records for cold email, and the registrar-panel version of the same mistake, including the record you cannot see, is in SPF on Namecheap.

    There is a second, quieter reason the copy-paste habit is expensive, and it has nothing to do with the count. SPF authorises the envelope sender rather than the address the reader sees, and DMARC only credits an SPF pass when the domain that passed aligns with the visible sender. A record inherited from another domain can therefore pass for a service that has nothing to do with the campaign, and align with nothing you intended, which reads as a healthy SPF result in any checker while contributing nothing to the outcome that matters.

    Two habits remove the question entirely on a sending fleet. Write each domain's record for that domain, from the platform that actually sends from it. And check the expanded lookup count at the moment the record is published rather than after mail starts failing, because the count is a property of other people's records and it moves without you.

    Our own position follows from the same reasoning rather than from a preference about DNS. We authenticate every sending domain before it carries a message and run one message per campaign, so a domain that fails authentication does not get a second attempt at the same person under a different pretext. That makes the record part of provisioning rather than part of debugging, and a domain with a problem gets replaced rather than repaired mid-campaign.

    Before flattening an SPF record
    • Yes: The expanded lookup count has been measured rather than estimated
    • Yes: Every include on the record belongs to a service that genuinely sends from this domain
    • Yes: Includes for services that no longer send have been removed first
    • Depends: If flattening automatically, the third-party dependency in the authentication path is accepted deliberately
    • No: This record was copied from another domain
    • No: Nobody owns re-checking a hand-flattened record on a schedule
    Deciding whether a record actually needs flattening. Two yes answers in the lower half usually mean the record, not the ceiling, is the problem.

    Sending domain is the object whose record this is, and the reason a purpose-built one rarely needs flattening. Email authentication is the layer SPF sits inside. DKIM is what a domain in permerror is resting on alone. Envelope sender is the address SPF actually authorises, which is not the address the reader sees. And MX record is the other DNS record a mail estate depends on.

    The short version

    SPF flattening swaps the lookup-causing terms in a record for the addresses they resolve to, because the specification caps those terms at ten and requires a permerror past it, while ip4 and ip6 are exempt from the count. It works, and it works by taking a copy of infrastructure somebody else maintains.

    The cost is silence: a flattened record decays as providers change their own ranges and nothing reports it, which is the same failure shape as the permerror it fixed. Automated flattening keeps the addresses current and puts a third party inside your authentication path.

    On an outbound fleet the question usually should not arise. One sending domain, one platform, one include, and a lookup count that stays in single figures. Where a record is over the ceiling, the first move is an inventory of who actually sends from that domain, because the cheapest fix is removing an include rather than expanding it.

    We run sending domains and the authentication behind them as part of the engagement. See how the campaigns work.

    Specification behaviour verified as of 30 August 2026 against RFC 7208. Verify current receiver behaviour with the mailbox providers you send to before relying on it.

    Questions

    Frequently asked questions.

    Frequently asked questions
    Why does SPF have a ten-lookup limit at all?
    RFC 7208 sets it to avoid unreasonable load on the DNS. Each include, a, mx, ptr or exists term, and the redirect modifier, costs a query at evaluation time, and included records are evaluated with their own lookup-causing terms counting against the same budget. Past ten the specification requires the implementation to return permerror rather than a verdict.
    What actually breaks when an SPF record exceeds ten lookups?
    Evaluation stops before reaching any verdict about the sending address, so SPF contributes nothing for every sender on that record rather than only the one that pushed it over. DMARC passes on either SPF or DKIM aligning, so the domain is left resting on DKIM alone. Nothing in a sending platform reports this and the record still looks present in a DNS panel.
    Is automated SPF flattening better than doing it by hand?
    It removes the staleness problem, because the service re-flattens on a schedule and keeps the addresses current. It replaces it with a dependency: your domain's ability to authenticate now runs through a third party's hosted record and their uptime, usually reached by a redirect. That can be a reasonable trade for a complicated mail estate, and it is a decision rather than a default.
    Should a cold email sending domain ever need flattening?
    Rarely. A purpose-built sending domain has one platform behind it, so it needs one include and its lookup count stays in single figures for its whole life. A fleet that needs flattening has usually inherited a primary domain's record by copy-paste, along with authorisations for services that will never send from it. The cheaper fix is removing includes rather than expanding them.