Skip to main content

Why You Can't CNAME the Apex

You buy example.com, you deploy something, and the host tells you:

Point your domain at d3jp940diwkqq6.cloudfront.net

So you open your DNS provider, go to add a CNAME for example.com, and either the form refuses you or — worse — it accepts and something subtly breaks. Meanwhile www.example.com takes the exact same CNAME without complaint.

This trips up nearly everyone once, and the usual explanation ("you just can't, use an ALIAS record") is true and explains nothing. The actual reason is a single sentence written in 1987, and it's worth understanding, because it's also a large part of why www stuck around for thirty years.

First, what the apex is

DNS is a tree of labels, and a zone is a contiguous chunk of that tree under one administrative authority. When you register example.com, the .com operators create a delegation — NS records in the .com zone saying "for anything at or under example.com, go ask these nameservers instead."

The apex of your zone is the zone's own name: example.com itself. You'll also see it called the zone apex, the root of the zone, the naked domain, or the bare domain. They all mean the same thing: the topmost name in the zone, with nothing to the left of it.

www.example.com is not the apex. It's an ordinary node inside the zone, one label deeper, and it is in no way special — it's a hostname with good PR. That difference is the whole story here.

Two record types are mandatory at an apex, and their presence is what makes it a zone at all:

  • SOA (Start of Authority) — exactly one. It declares this name as the top of a zone and carries the zone's operational parameters: the primary nameserver, the admin contact, the serial number, refresh/retry/expire timers, and the negative-caching TTL.
  • NS — the authoritative nameservers for the zone. These have to match the delegation the parent published, or resolution gets inconsistent.

This is from RFC 1034, and it's not optional or conventional. A name with no SOA is not a zone apex. A zone apex with no SOA is broken.

So: the apex always has other records at it. Hold onto that.

The rule

RFC 1034 §3.6.2, from November 1987:

If a CNAME RR is present at a node, no other data should be present; this ensures that the data for a canonical name and its aliases cannot be different.

RFC 2181 §10.1 later tightened "should" into the operational requirement everyone actually implements, with one carve-out for DNSSEC records (RRSIG, NSEC) which must be allowed to sit alongside a CNAME for the signature chain to work.

That's it. That's the whole restriction:

A name with a CNAME may have no other records.

Combine it with the previous section and the conclusion is forced. The apex must have SOA and NS. A CNAME forbids all other records. Therefore the apex can never hold a CNAME. It isn't a policy decision by your DNS provider or a limitation of their UI — it's arithmetic on two rules.

Why the rule exists

It's tempting to read the restriction as arbitrary. It isn't, and the reason gets at what a CNAME actually means.

A CNAME does not say "also look over there." It says this name IS that name — the target is the canonical name and this one is merely an alias for it. The correct behaviour on encountering a CNAME is to abandon the name you asked about entirely and restart the query against the target, for whatever record type you originally wanted.

That's a total substitution, which is why coexistence is incoherent. Suppose you could write:

example.com.   CNAME   target.example.net.
example.com. MX 10 mail.example.com.

Now a mail server looks up MX for example.com. Two contradictory answers are available: follow the CNAME and use whatever MX target.example.net has, or use the local MX record sitting right there. Nothing in the protocol says which wins. Two resolvers could reasonably disagree, and — because answers get cached independently by record type — the same resolver could disagree with itself depending on which record it happened to cache first.

The phrase in the RFC is precise about the goal: "the data for a canonical name and its aliases cannot be different." An alias that only partially aliases isn't an alias. So the spec forbids the ambiguity rather than trying to arbitrate it.

Once you see it that way, the apex restriction stops being a special case. There's no rule about apexes at all. There's one rule about CNAMEs, and the apex just happens to be a name that can never satisfy it.

The same logic bites elsewhere, for the same reason: you can't put a CNAME at a delegation point either, because that name already carries NS records for the child zone.

Why this suddenly started mattering

The rule is from 1987 and caused nobody much grief for a long time, because you pointed domains at IP addresses. You had a server, the server had an address, you wrote an A record. No aliasing needed.

Modern hosting broke that assumption. CloudFront, ALBs, Netlify, Vercel, Heroku, Fastly, GitHub Pages — none of them will give you a stable IP, because they don't have one to give. The address behind d3jp940diwkqq6.cloudfront.net varies by region, by point of presence, by load, and changes without notice. The hostname is the contract; the addresses behind it are an implementation detail they reserve the right to change at 3am.

"Follow this hostname wherever it goes" is precisely what CNAME is for. So the entire industry standardised on an instruction that works everywhere in your zone except at the one name you actually want to use.

And here's the bit worth noticing. For years, this made the layout obvious:

  • www.example.com → one-line CNAME to your CDN. Trivial.
  • example.com → not expressible. A research project.

Which is a genuine, unglamorous, technical reason www outlived its usefulness as a convention. It wasn't nostalgia. www was the one that worked. The apex was the awkward case, so plenty of sites made www canonical and redirected the bare domain to it — the opposite of what most people do today.

The workarounds

Provider-side pseudo-records (ALIAS / ANAME / CNAME flattening)

The one nearly everybody uses. Route 53 calls it an alias record, Cloudflare calls it CNAME flattening, DNSimple and others call it ALIAS or ANAME.

The crucial thing to understand: none of these are a DNS record type. There is no ALIAS record on the wire, and no RFC defines one. You will never see one in a packet capture.

What actually happens is that your authoritative nameserver does the work. You tell Route 53 "this apex is an alias for d3jp940diwkqq6.cloudfront.net." When a query arrives for example.com, Route 53 resolves that target itself, server-side, and returns the resulting addresses as ordinary A/AAAA records for example.com. The client sees a completely normal answer and never learns aliasing was involved. The protocol is untouched; the indirection is hidden inside one implementation.

That design has consequences worth knowing:

  • It's a provider feature, not a DNS feature. It only exists if whoever hosts your zone implements it. Move your DNS to a provider that doesn't, and your apex stops working.
  • It can't be replicated by a zone transfer. What AXFRs out is the flattened A records at whatever they were when the transfer happened, not the aliasing intent.
  • The resolution happens from the nameserver's vantage point, not the client's. If the target uses geographic DNS load-balancing, the target sees your DNS provider's location rather than the end user's, which can route people to the wrong region. In practice this is a non-issue for Route 53 → CloudFront, since alias targets there are handled internally and CloudFront does its own edge routing on the anycast address anyway. It's a real consideration when flattening a CNAME to a third-party host.
  • Targets are often restricted. Route 53 alias records can only point at AWS resources (CloudFront, ALB, S3 website endpoints, API Gateway…) or another record in the same hosted zone. You can't alias to an arbitrary external hostname.
  • They're usually free to query. Route 53 doesn't bill for alias queries to AWS targets, where a normal record costs per million. Minor, but real at volume.

You also need this at the apex specifically. Once you're one label deep — www — a plain CNAME works fine and none of the above applies.

Just hardcode the A records

Look up the addresses, write them in, move on. It works right up until it doesn't. Providers rotate addresses deliberately and without telling you, so this is a time bomb with a fuse of unknown length. Defensible for a server whose IP you control. Not defensible in front of a CDN.

Make www canonical and redirect the apex

Some registrars offer an HTTP redirect service at the apex — a tiny web server whose only job is to 301 example.com to www.example.com. The apex gets A records pointing at the registrar's redirector, www gets the CNAME, and the awkward name is handled at the HTTP layer instead of the DNS layer.

This is why some large sites still serve www as canonical. It's not a stylistic preference left over from 1998; it was the shape that worked.

HTTPS/SVCB records — the actual protocol fix

RFC 9460 (2023) introduced the SVCB and HTTPS record types, and they finally address this at the protocol level rather than around it.

An HTTPS record in AliasMode — priority field set to 0 — does at the apex what CNAME cannot:

example.com.   HTTPS   0 target.example.net.

This is legal at the apex because it's a normal record type with no exclusivity rule. It coexists with SOA and NS perfectly happily. RFC 9460 calls out apex aliasing as an explicit design goal, not an accident.

The catch is client support. HTTPS records are genuinely deployed — Chrome, Firefox and Safari query them, mainly for HTTP/3 advertisement and Encrypted Client Hello — but they're HTTPS-specific by construction, and anything that isn't a modern browser will ignore them entirely. You still need A/AAAA records at the apex for everyone else, which means you still need the provider-side alias, which means the HTTPS record isn't yet replacing anything.

It's the correct long-term answer and not yet a usable one on its own. Worth knowing exists; not worth restructuring your zone around today.

What about DNAME?

DNAME (RFC 6672) is the record people reach for next, and it doesn't help here.

DNAME redirects an entire subtree: a DNAME at example.com rewrites anything.example.com to anything.example.net. What it explicitly does not do is affect the owner name itself. example.com is not covered by its own DNAME.

So a DNAME at the apex would redirect every subdomain you have while leaving the apex — the one name you were trying to fix — exactly as broken as before. It solves the opposite problem to the one you have.

The short version

  • A zone apex must carry SOA and NS records. That's what makes it a zone.
  • A CNAME forbids any other record at the same name, because a CNAME means total substitution and partial aliasing would be ambiguous.
  • Those two rules can't both hold at the apex, so a CNAME there is impossible. There is no separate "apex rule."
  • ALIAS/ANAME/flattening are one authoritative nameserver quietly resolving the target for you and returning plain A records. Convenient, invisible to clients, and entirely proprietary.
  • www never had this problem, which is a real reason the convention survived long past the point anyone could explain why it existed.

Seen in the wild: the csv-helper.com fix, where the apex is a Route 53 alias to CloudFront and www is an ordinary record pointed at the same place.

Comments

No comments yet. Be the first!