Type something to search...
What is CNAME flattening and why do you need it?

What is CNAME flattening and why do you need it?

CNAME flattening is a technique where your authoritative DNS server follows a CNAME chain itself and returns the final A and AAAA records to the client, instead of returning the CNAME. The visitor's resolver never sees an alias, only IP addresses. You need it because the DNS rules forbid a CNAME at the root of your domain, yet most modern hosting platforms, CDNs and load balancers only give you a hostname to point at. Flattening lets you create what looks like a CNAME at example.com without breaking your email or other apex records.

The term was popularised by Cloudflare, which flattens apex CNAMEs automatically, and today it's often used for any provider's version of the idea. In this article you'll learn exactly why a CNAME can't sit at the apex and what goes wrong if you try, how flattening works step by step, how Cloudflare applies it, how to spot a flattened record with dig, how to build a simple version yourself when your provider doesn't offer it, and the cases where flattening causes problems of its own.

Why You Can't Put a CNAME at the Root Domain

A CNAME record says "this name is an alias for another name". RFC 1034 adds a strict rule: if a name has a CNAME, it must not have any other data. The reasoning is simple. When a resolver finds a CNAME, it restarts the lookup at the target, for every record type. If the name also had its own MX or TXT records, the resolver wouldn't know which to believe.

The root of a zone, called the apex, always has at least two record types: the SOA record and the NS records. Most apexes also have MX records for email and TXT records for SPF and domain verification. So a CNAME at the apex always breaks the rule.

What Happens If You Try Anyway

Many DNS servers simply refuse to load a zone with an apex CNAME. BIND's named-checkzone will reject it:

$ORIGIN example.com.
@    3600  IN  SOA    ns1.example.com. hostmaster.example.com. 2026101401 7200 3600 1209600 3600
@    3600  IN  NS     ns1.example.com.
@    3600  IN  NS     ns2.example.com.
@    300   IN  CNAME  app.platform.example.net.
@    3600  IN  MX     10 mx1.example.com.
named-checkzone example.com db.example.com
dns_master_load: db.example.com:5: example.com: CNAME and other data
zone example.com/IN: loading from master file db.example.com failed: CNAME and other data
zone example.com/IN: not loaded due to errors.

Some web-based DNS panels allow it, though, and the results are messy. Imagine a resolver that has cached the CNAME and is then asked for your MX record:

dig example.com MX +noall +answer
example.com.               300   IN  CNAME  app.platform.example.net.

The resolver follows the CNAME and asks for MX records at app.platform.example.net. That hostname almost certainly has none, so mail servers fall back to delivering to the platform's A record. Your email ends up at your web host, which rejects it. Depending on what's cached, some senders deliver correctly and others don't, which makes the fault intermittent and confusing.

How CNAME Flattening Works

Flattening keeps the convenience of a CNAME but moves the work from the visitor's resolver to your DNS provider:

  1. You create a CNAME at the apex in your provider's dashboard, pointing example.com at app.platform.example.net.
  2. The provider stores it internally, but never serves it as a CNAME.
  3. A resolver asks for example.com A. The provider's authoritative server resolves app.platform.example.net itself, following any further CNAMEs in the chain, until it reaches A records.
  4. The provider answers with those A records, as if they were stored directly on example.com. AAAA queries are handled the same way.
  5. Other record types are unaffected. An MX query for example.com returns your real MX records, because, as far as the outside world can tell, there's no CNAME at the apex.

The "flattening" in the name refers to collapsing a chain of aliases into a single, flat answer:

Without flattening:
  example.com          CNAME  app.platform.example.net
  app.platform...      CNAME  lb-eu.platform.example.net
  lb-eu.platform...    A      203.0.113.20

With flattening, the resolver only sees:
  example.com          A      203.0.113.20

A side benefit is speed. The resolver gets the final answer in one step, rather than having to chase each alias in turn.

CNAME Flattening on Cloudflare

Cloudflare offers flattening in a few forms:

  • At the apex, on every plan: If you create a CNAME on the root domain, Cloudflare flattens it automatically. You don't need to turn anything on.
  • For other names, on paid plans: You can choose to flatten every CNAME in the zone, or flatten individual records. That's mainly useful when something downstream can't cope with CNAMEs, or when you want to hide the target hostname.
  • Proxied records are different: If the orange cloud is on, Cloudflare answers with its own anycast IP addresses and proxies the traffic, so the target's addresses are never published at all. Flattening only applies to DNS-only (grey cloud) records.

Other providers implement the same idea under the names ALIAS or ANAME, and Route 53 and Azure DNS offer alias records restricted to their own cloud resources. The behaviour on the wire is the same: plain A and AAAA records at the apex.

Checking Whether a Record Is Flattened

From the outside, a flattened apex looks exactly like a normal A record. To confirm what's happening, compare the apex with the target and check that no CNAME is returned:

dig example.com A +noall +answer
example.com.         300   IN   A    203.0.113.20
example.com.         300   IN   A    203.0.113.21
dig app.platform.example.net A +noall +answer
app.platform.example.net.   60   IN   CNAME   lb-eu.platform.example.net.
lb-eu.platform.example.net. 60   IN   A       203.0.113.20
lb-eu.platform.example.net. 60   IN   A       203.0.113.21

The addresses match, and the apex answer has no CNAME. Query your authoritative nameserver directly to rule out caching:

dig @ns1.example.com example.com A +norecurse

Then confirm that the other apex records still work:

dig example.com MX +short
dig example.com TXT +short

If those return your real MX and TXT records, flattening is doing its job.

Building Your Own Flattening

If your DNS provider doesn't support flattening or ALIAS records, you can approximate it with a scheduled job that resolves the target and updates the apex A records through the provider's API. This Python example uses dnspython and boto3 with Route 53, but the same approach works with any API:

import boto3
import dns.resolver

ZONE_ID = "Z0123456789EXAMPLE"
APEX = "example.com."
TARGET = "app.platform.example.net"
TTL = 60


def resolve(rtype):
    try:
        return sorted(r.to_text() for r in dns.resolver.resolve(TARGET, rtype))
    except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
        return []


def current(client, rtype):
    resp = client.list_resource_record_sets(
        HostedZoneId=ZONE_ID, StartRecordName=APEX, StartRecordType=rtype, MaxItems="1"
    )
    for rrset in resp["ResourceRecordSets"]:
        if rrset["Name"] == APEX and rrset["Type"] == rtype:
            return sorted(r["Value"] for r in rrset.get("ResourceRecords", []))
    return []


def main():
    client = boto3.client("route53")
    changes = []
    for rtype in ("A", "AAAA"):
        wanted = resolve(rtype)
        if wanted and wanted != current(client, rtype):
            changes.append({
                "Action": "UPSERT",
                "ResourceRecordSet": {
                    "Name": APEX,
                    "Type": rtype,
                    "TTL": TTL,
                    "ResourceRecords": [{"Value": ip} for ip in wanted],
                },
            })

    if changes:
        client.change_resource_record_sets(
            HostedZoneId=ZONE_ID,
            ChangeBatch={"Comment": "Flatten apex to " + TARGET, "Changes": changes},
        )
        print("Updated:", [c["ResourceRecordSet"]["Type"] for c in changes])
    else:
        print("No change")


if __name__ == "__main__":
    main()

Run it every few minutes from cron:

*/5 * * * * /usr/bin/python3 /opt/flatten/flatten.py >> /var/log/flatten.log 2>&1

This only covers the target's addresses as seen from where the script runs, and there's always a short window between the target changing and your records updating. Keep the TTL low, and note that the script deliberately does nothing if the target returns no addresses, so a temporary resolution failure doesn't wipe out your apex. For Route 53 targets that are AWS resources, a native alias record is better, and for most other cases a provider with built-in flattening is simpler and more reliable.

When Flattening Causes Problems

Flattening fixes the apex rule, but because the target's DNS no longer talks to the visitor's resolver directly, a few things can change.

CDN Edge Selection

Many CDNs use DNS to send each visitor to a nearby edge server. They decide based on the resolver that's asking. With flattening, the resolver asking the CDN is your DNS provider, not the visitor's. A visitor in Sydney might be sent to an edge server chosen for the provider's location instead.

Large providers soften this by resolving from many locations or by sending EDNS Client Subnet information to the target, but results vary. If the platform gives you a dedicated anycast IP or documented A records for the apex, those avoid the issue entirely.

Platform Verification

Some hosting and SaaS platforms verify a custom domain by checking that it returns a CNAME to them. A flattened record returns A records instead, so the check can fail even though traffic arrives correctly. Most platforms that support apex domains document an alternative, such as a TXT verification record or a set of A records to compare against. Follow the platform's apex instructions rather than its subdomain ones.

TTL and Freshness

The flattened answer can only be as fresh as the provider's cached copy of the target. If the target's IPs change suddenly, visitors may see old addresses for a short time. Reputable providers respect the target's TTL, but it's worth knowing that there are two layers of caching instead of one.

Portability

A flattened CNAME is a provider feature, not a standard record. Zone exports and secondary DNS transfers can't reproduce it, so you'll need to recreate it if you change providers or add a secondary.

Do You Need CNAME Flattening?

You need flattening, or an equivalent ALIAS feature, if all of these are true:

  • You want visitors to reach your site on the bare domain, such as example.com, not only www.example.com.
  • Your hosting platform, CDN or load balancer gives you a hostname rather than stable IP addresses.
  • You also have, or might need, MX, TXT or other records at the apex.

You don't need it if:

  • The platform provides stable apex IP addresses you can use in A records.
  • You only serve the site on www or another subdomain, where a normal CNAME is fine, and redirect the apex to it with a static A record pointing at a redirect service.

For subdomains, stick with ordinary CNAMEs unless you have a specific reason to flatten. They're standard, portable and let the target's DNS make the best routing decisions.


FAQ: CNAME Flattening

They achieve the same result. CNAME flattening is the name Cloudflare uses, while other providers call it ALIAS or ANAME. In each case the provider resolves the target and returns A and AAAA records instead of a CNAME.

It protects it. Because no CNAME is served at the apex, your MX and TXT records stay visible and work normally. An unflattened apex CNAME is what breaks email.

Usually it helps slightly, because resolvers get the final answer in one step. The main risk is with CDNs that pick edge servers based on the resolver's location, which may be less accurate when your DNS provider does the lookup.

Some providers let you, often on paid plans. It's rarely needed, since CNAMEs are allowed on subdomains, but it can help when a downstream system can't follow CNAMEs or you don't want to reveal the target hostname.

Some platforms check for a CNAME pointing at them. A flattened record returns A records instead. Use the platform's apex domain instructions, which usually offer A records or a TXT verification record.

Yes, on providers that support both. The provider signs the synthesised A and AAAA answers as it creates them, so validating resolvers can still verify them.


Conclusion

CNAME flattening exists because DNS forbids a CNAME at the root of a domain, while modern platforms almost always hand you a hostname. By resolving the alias on the authoritative server and returning plain A and AAAA records, flattening gives you the flexibility of a CNAME without hiding your MX, TXT, NS and SOA records.

If your provider supports it, it's usually the simplest way to put a platform-hosted site on your bare domain. Keep an eye on the side effects, especially CDN edge selection and platforms that verify by CNAME, and remember that it's a provider feature rather than a portable record. For subdomains, a normal CNAME remains the right tool.

Tags :
Share :

Related Posts

What is the difference between an A record and a CNAME record?

What is the difference between an A record and a CNAME record?

The difference between an A record and a CNAME record is what they point to. An A record points a hostname directly at an IPv4 address, such

Dive Deeper
What are the best DNS providers for websites?

What are the best DNS providers for websites?

The best DNS providers for most websites are Cloudflare for a fast, free, easy starting point, Amazon Route 53 if you already run on AWS, **G

Dive Deeper
What are the best public DNS resolvers?

What are the best public DNS resolvers?

The best public DNS resolvers for most people are Cloudflare (1.1.1.1) for speed and privacy, Google Public DNS (8.8.8.8) for reliability and

Dive Deeper