You Can't Put a CNAME on the Apex (Here's Why)

Every CDN wants you to point your root domain at a hostname. DNS has forbidden exactly that since 1987 — so the industry built a pile of non-standard hacks, and the one real fix still doesn't work in your browser.

You sign up for a CDN, or a static host, or some SaaS that lives at something.theirdomain.com, and they hand you an instruction: “Point your domain at us with a CNAME.” Fine. You want example.com — the bare domain, the thing people actually type — to serve their content. So you open your DNS panel, try to add a CNAME at the apex, and your provider either rejects it outright or, worse, accepts it and quietly breaks your email.

This is one of the oldest footguns in DNS, and almost nobody who hits it understands why it’s forbidden. It’s not your registrar being difficult. It’s a rule from 1987 that has never once bent.

The rule is older than the web

CNAME means “canonical name” — it says “this name is an alias; go look up that other name instead.” RFC 1034, the document that defined how DNS actually works, laid down a constraint in §3.6.2 that reads, paraphrased: if a CNAME record exists at a name, no other record type may exist there. RFC 2181 §10.1 later restated it in one sentence because people kept getting it wrong: “If a CNAME RR is present at a node, no other data should be present.”

The reasoning is clean. A CNAME is a total redirect. If www.example.com is a CNAME to cdn.provider.net, then every query for www.example.com — A, AAAA, TXT, MX, anything — is supposed to chase the alias. There’s no room for www.example.com to also have its own MX record, because the CNAME already said “I’m not the real name, go elsewhere.” Alias and local data are contradictory instructions. So the spec bans the combination.

Now look at the apex — example.com with nothing in front. The apex is not optional real estate. Every zone, by definition, carries an SOA record (the zone’s serial number and timing) and NS records (which nameservers are authoritative) at the apex. Those are mandatory. A zone without them isn’t a zone. RFC 1035 requires them; they are what makes example.com a delegated, hosted domain at all.

So the apex always has other data — SOA and NS, at minimum. And a CNAME can’t coexist with other data. The two facts collide, and the collision is total: you can never, on a spec-compliant server, put a CNAME at the apex. It’s not “discouraged.” It’s structurally impossible without producing a zone that’s broken by definition. The DNS servers that “let” you do it are either lying to you or about to eat your NS records.

Which is why the whole industry cheated

Here’s the thing that makes this interesting rather than just annoying: the modern web made apex CNAMEs necessary at exactly the moment DNS made them impossible.

CDNs and cloud load balancers don’t give you a stable IP. They give you a hostname — d1234.cloudfront.net, myapp.herokudns.com — and that hostname resolves to whatever set of IPs is healthiest and closest right now. The entire point is that the IP behind the name changes without telling you. If you hardcode an A record at your apex pointing at today’s IP, you’ve defeated the CDN: tomorrow that IP moves and your site goes dark. You need the alias behavior at the apex. And you can’t have it.

So DNS providers invented their way around the spec. The names differ but the trick is identical: flattening. You configure something that looks like an apex CNAME — Route 53 calls it an Alias record, DNSimple and others call it ANAME, Cloudflare calls it CNAME Flattening. The authoritative nameserver, when a client asks for the apex’s A record, quietly resolves the target hostname itself, on its own, and returns the resulting IP addresses as though they were ordinary A records sitting at your apex. The client never sees a CNAME. It sees plain A/AAAA records, which are perfectly legal at the apex. The SOA and NS records stay put. Nothing is violated on the wire.

Cloudflare offers flattening for free and turns it on automatically when you try to CNAME the apex. Route 53, DNSimple, NS1, Dyn, Bunny — most serious managed-DNS providers have some flavor of it now. It works. Millions of domains run on it.

It also has a cost that nobody mentions in the setup wizard. When your nameserver resolves the target instead of the client’s resolver, the geographic steering breaks. A CDN hands out different IPs depending on where the query comes from — that’s how it sends a user in Frankfurt to a Frankfurt edge. But with flattening, the query the CDN sees comes from your DNS provider’s resolver, not from the user. So the CDN optimizes for your nameserver’s location, and every visitor gets pointed at whatever edge is close to that. On a small site you’ll never notice. On a global one it’s the difference between a 20ms and a 150ms first byte, and it is maddening to debug because the DNS looks completely correct. You also inherit a TTL question: the synthesized A records get a TTL your provider picks, not the target’s, so a fast-failing-over origin can get pinned to an address your zone keeps handing out after it’s already dead.

ANAME almost became a real standard, by the way. There was an IETF draft, draft-ietf-dnsop-aname, worked on from 2017 through 2019. It reached its fourth revision and then expired in January 2020 without ever becoming an RFC. The idea was sound; the working group couldn’t agree on how resolvers versus authoritative servers should split the resolution work, and it died in committee. So every ANAME/ALIAS implementation you’re using today is a proprietary extension that happens to share a name, not an interoperable standard. Two providers’ ANAME records behave subtly differently, and neither is “correct” because there’s nothing to be correct against.

The actual fix exists. Your browser ignores it.

In 2023 the IETF finally shipped the real answer: RFC 9460, the SVCB and HTTPS resource records. Buried in it is exactly the mechanism the apex needed. An HTTPS record with priority 0 is what the spec calls AliasMode — and RFC 9460 says its primary purpose, in so many words, is to allow aliasing at the zone apex where CNAME is not allowed. It’s a CNAME-for-the-apex that coexists cleanly with SOA and NS, because it only speaks to a specific service (HTTPS) rather than hijacking the whole name the way CNAME does. Standardized, interoperable, apex-safe. The thirty-year-old problem, solved on paper.

And then you go to use it and discover the punchline. The browsers query HTTPS records — Chrome, Firefox, Safari all do, and they’ll happily read ServiceMode parameters out of them, things like which ALPN protocols the server speaks or an Encrypted Client Hello key. But AliasMode, the priority-0 record, the one that actually solves the apex problem? In practice only Apple’s stack follows it. Chromium and Firefox read the HTTPS record and then don’t chase the alias — they won’t do the follow-up resolution that AliasMode requires. Which means the two engines carrying the overwhelming majority of web traffic look at the one record designed to fix apex aliasing and shrug.

So the state of the art in 2026 is: the apex CNAME problem is solved by a published standard that the clients haven’t implemented. Until Chromium and Firefox learn to follow a priority-zero HTTPS record, you’re still stuck choosing between your provider’s flattening hack and giving up on a bare domain entirely.

What to actually do

If you need your apex to point at a CDN or a hostname today — and you almost certainly do — use your provider’s flattening. It’s the pragmatic answer and it’s fine for most sites. Just know what you traded: you moved the target’s resolution onto your nameserver, so if you run anything geo-sensitive, verify where your visitors are actually being sent rather than trusting that the DNS “looks right.” Check the TTL on the flattened records too.

And when someone confidently tells you to “just add a CNAME at the root,” you now know the honest reply: you can’t, nobody can, the spec forbade it before most of us were writing DNS records, and the clean replacement has been sitting in RFC 9460 for three years waiting for the browsers to catch up.

Continue the conversation

← Back to Blog