CNAME, A and ALIAS Records: Which One Belongs at the Apex
You are pointing a domain at a service that gives you a hostname rather than an IP address — a hosting platform, a CDN, a verification target. You go to add the record, and the form asks for a type. The dropdown offers CNAME, and then a DNS tutorial somewhere suggests ALIAS instead. Within ten minutes you have found three mutually contradictory answers about which one is correct at the root of your domain.
Most of that confusion comes from one fact that rarely gets stated plainly: ALIAS is not a DNS record type. It is a vendor extension, it has no RFC behind it, and it does not exist on every provider. Getting this right starts with knowing what each option actually is.
The three things people call a record type
An A record maps a name to an IPv4 address. AAAA does the same for IPv6. These are the only record types that resolve a hostname to an address, and they are the ones an authoritative DNS server can answer definitively. Their weakness is that they are static: if your origin’s IP changes, your site goes down until you update the record.
A CNAME record maps a name to another name. The client then resolves that second name, wherever it leads. This is what you want whenever the thing you are pointing at can change its address without telling you — hosting platforms, CDNs, and most modern PaaS products use this pattern deliberately, because it lets them move you between machines without you touching DNS. The weakness is a hard rule in the standards: if a name has a CNAME, it cannot have any other data.
ALIAS — and its aliases. Several DNS providers offer something that behaves like a CNAME but is permitted at the root of a zone. It is called ALIAS at some providers, ANAME at others, and simply “Alias” at others. There is no specification governing it. Each implementation resolves it in its own way, some at query time and some by periodically polling the target and serving back an A record.
That last point is the practical one. Because ALIAS is a provider-specific feature rather than a DNS standard, it does not transfer. Move your DNS to a different provider and the record either vanishes, converts to something else, or is silently reinterpreted. If you have ever migrated a zone file and found a hostname that stopped resolving for no visible reason, a proprietary pseudo-record is a common cause.
Why the apex is the awkward case
Every zone must publish a SOA record and at least one NS record at its own apex. Under the rules that govern CNAME, a name carrying a CNAME cannot carry anything else — so a CNAME at the apex would collide with the records the apex is required to have. That is the entire reason “you cannot CNAME your root domain” became folk wisdom, and it is still true in the standards.
It is also a nuisance, because the apex is exactly where you want the flexible kind of record, and where providers usually issue a hostname rather than an address.
Providers solve it three ways. They invent a pseudo-record (ALIAS). They return an address instead of the alias by resolving it themselves at query time. Or they simply permit a CNAME at the apex and handle the collision for you. Cloudflare takes the third route, calls it CNAME flattening, and documents the behaviour precisely enough to be worth reading before you configure anything.
How CNAME flattening actually behaves
The mechanism is straightforward: Cloudflare resolves the CNAME chain — which may be one lookup or several — and returns the final IP addresses to the client instead of the CNAME. Queries resolve faster and the apex gets the flexibility of a name-based record.
The settings are more specific than most guides suggest, and the differences matter:
| Scope | Availability |
|---|---|
| CNAME at the zone apex | Flattened by default on all plans, including Free |
| A proxied CNAME, at any name | Flattened by default |
| All CNAME records (zone-wide) | Paid plans only |
| A single specific CNAME record | Paid plans only, and a per-record “Flatten” toggle |
Three footnotes from the same documentation, each of which resolves a real-world symptom:
- If the CNAME target sits in the same zone as the record, Cloudflare flattens it regardless of the setting — the zone-wide and per-record options do not apply.
- A per-record flatten adds a tag called
cf-flatten-cnameto the record, so it survives an export-and-import cycle. Without the tag, that configuration is easy to lose in a migration. - The per-record Flatten toggle is unavailable in three cases: the record is at the apex, the record is proxied, or zone-wide flattening is already on and therefore cannot be overridden.
One more consequence worth knowing before it confuses you: for a proxied name, a query for a different record type does not reach into the target zone. If abc.example.com is a proxied CNAME pointing at a hostname that carries a TXT record, a TXT query against abc.example.com returns nothing. The CNAME does not forward arbitrary record types.
Why this matters for platform deployments
If you deploy to Cloudflare Pages and wonder how a Pages site can live on a bare testedhost.com when Pages hands out a *.pages.dev hostname, this is the answer — and the documentation says so directly: CNAME flattening is what allows a root custom domain on a Pages site.
The same applies to any platform that gives you a hostname: you point the apex at it with a CNAME, the DNS provider flattens it, and the client never sees a CNAME at the apex. On a provider without flattening you would be stuck either using www as your canonical host or pinning an A record to an address that will eventually change.
Three failures that get misdiagnosed
A dangling CNAME looks like a propagation problem. If the final target in a CNAME chain has no A or AAAA records, flattening has nothing to return and produces an empty response. Tools will report NODATA, and it looks exactly like a record that has not propagated yet — the same symptom, a completely different cause and fix. A typo in a target hostname gets you here, as does pointing at a hostname that was decommissioned.
Cross-account CNAMEs are blocked outright. Pointing a CNAME from one Cloudflare account at a hostname in a different Cloudflare account is prohibited and returns Error 1014. This trips people migrating between accounts, or building the same site on a second account for testing. The block is deliberate, and there is no setting to override it.
Zone-wide flattening can break domain verification. If a third-party service verifies your ownership by reading a CNAME record back — a common pattern — turning on flattening for all CNAME records may cause verification to fail, because the record is no longer returned as a CNAME. This is why the zone-wide option is a blunt instrument, and why the per-record toggle is the better fit when you need precision.
Diagnosing it in one command
Do not reason about this from a dashboard. Query the name and read what comes back:
dig +short example.com
dig +short CNAME example.com
The three possible shapes tell you three different things:
- An IP address — the name is flattened, or has an A record. Working as intended.
- A hostname — you are getting an unflattened CNAME. Either the record is not at a scope that flattens on your plan, or it is DNS-only and flattening is off.
- Nothing — check the CNAME chain for a dangling target before you assume propagation. Follow the chain manually, one hop at a time, and confirm the final name has an A or AAAA record.
That last check is the one worth building into your habits. “It has not propagated yet” is the most common wrong answer in DNS troubleshooting, and as often as not the real problem is a chain terminating at a name that resolves to nothing.
The decision, in practice
| Situation | Use |
|---|---|
| Platform gave you a hostname (Pages, Netlify, Vercel, a CDN) | CNAME — at the apex too, on a provider that flattens |
| You must point at a fixed IP you control | A (and AAAA if the host has IPv6) |
| You are on a provider whose only apex option is a pseudo-record | Whatever it calls it — and note it in your migration checklist |
| Third-party service verifies ownership by reading a CNAME | CNAME, and make sure flattening is not hiding it |
Two habits carry across all of them. Prefer the record that follows the target when the target can move, because a static A record pointing at a dynamic address is a outage with a delay timer on it. And when a provider offers you a record type that no RFC defines, use it if you must, but write down that you did — because it is the one part of your zone file that will not mean the same thing on the other side of a migration.
Written by TestedHost. Every recommendation on this site comes from running the setup described, on a live deployment — not from a vendor spec sheet. Spotted something out of date? Tell us.