A hosting platform gives you a hostname, and the apex of your zone cannot be a CNAME. CNAME flattening bridges the gap: your DNS provider resolves the hostname on its side and answers with the addresses at the end of the chain. The cost is visibility. Once flattened, the alias no longer exists in public DNS, and the only record of what your apex follows is your provider’s configuration.

Why the apex needs a workaround

RFC 2181 (section 10.1) says a name that holds a CNAME may hold no other data, DNSSEC records aside. Every zone apex must hold SOA and NS records. So this zone is not valid DNS, even though the same CNAME at www.example.com would be fine:

example.com.   3600  IN  SOA    ns1.dns-host.example. hostmaster.example.com. ...
example.com.   3600  IN  NS     ns1.dns-host.example.
example.com.   300   IN  CNAME  project.platform.example.

DNS providers therefore let you configure a hostname target at the apex while serving something else on the wire. If the difference between address records and aliases is new to you, start with A records versus CNAME records.

A flattened apex, seen from outside

and.guide is attached to the Cloudflare Pages project and-guide. For an apex domain, Cloudflare’s Pages documentation has you move the zone to Cloudflare’s nameservers, after which Cloudflare creates a CNAME record pointing at the project’s pages.dev hostname. Cloudflare flattens a CNAME at the apex by default on every plan. Here is the result, straight from the zone’s nameserver.

Live capture, 26 September 2026. Asking and.guide’s authoritative server for a CNAME at the apex, with recursion off:

dig @roan.ns.cloudflare.com and.guide CNAME +norec
; <<>> DiG 9.10.6 <<>> @roan.ns.cloudflare.com and.guide CNAME +norec
; (3 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11760
;; flags: qr aa; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;and.guide.			IN	CNAME

;; AUTHORITY SECTION:
and.guide.		1800	IN	SOA	frida.ns.cloudflare.com. dns.cloudflare.com. 2414193944 10000 2400 604800 1800

;; Query time: 8 msec
;; SERVER: 173.245.59.226#53(173.245.59.226)
;; WHEN: Sat Sep 26 23:49:35 KST 2026
;; MSG SIZE  rcvd: 101

Live capture, 26 September 2026. The same server, asked for addresses:

$ dig +nocmd @roan.ns.cloudflare.com and.guide A +norec +noall +answer
and.guide.		300	IN	A	172.66.47.12
and.guide.		300	IN	A	172.66.44.244
$ dig +nocmd @roan.ns.cloudflare.com and.guide AAAA +norec +noall +answer
and.guide.		300	IN	AAAA	2606:4700:310c::ac42:2f0c
and.guide.		300	IN	AAAA	2606:4700:310c::ac42:2cf4

Live capture, 26 September 2026. The target at its own source, less than a minute later. pages.dev delegates each project name to separate nameservers, so the first stop is a referral:

$ dig +nocmd pages.dev NS +noall +answer
pages.dev.		1231	IN	NS	adi.ns.cloudflare.com.
pages.dev.		1231	IN	NS	karl.ns.cloudflare.com.
$ dig +nocmd @adi.ns.cloudflare.com and-guide.pages.dev A +norec +noall +comments +authority
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4176
;; flags: qr; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; AUTHORITY SECTION:
and-guide.pages.dev.	300	IN	NS	dane.ns.cloudflare.com.
and-guide.pages.dev.	300	IN	NS	kristin.ns.cloudflare.com.

$ dig +nocmd @dane.ns.cloudflare.com and-guide.pages.dev A +norec +noall +answer
and-guide.pages.dev.	300	IN	A	172.66.44.244
and-guide.pages.dev.	300	IN	A	172.66.47.12
$ dig +nocmd @dane.ns.cloudflare.com and-guide.pages.dev AAAA +norec +noall +answer
and-guide.pages.dev.	300	IN	AAAA	2606:4700:310c::ac42:2cf4
and-guide.pages.dev.	300	IN	AAAA	2606:4700:310c::ac42:2f0c
$ dig @dane.ns.cloudflare.com and-guide.pages.dev A +norec | grep flags
;; flags: qr aa; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
; EDNS: version: 0, flags:; udp: 1232

Three things stand out:

  • The CNAME query returns status: NOERROR, ANSWER: 0, and the aa flag. The zone’s own server is saying the apex exists and has no CNAME. That is a NODATA answer, and it is correct: flattening never publishes the alias.
  • The apex’s A and AAAA sets match the target’s address for address, both with a TTL of 300. Only the order differs, and DNS makes no promise about order.
  • adi.ns.cloudflare.com, a pages.dev nameserver, answered without aa and returned two NS records instead: and-guide.pages.dev is a delegated zone of its own. Following the referral to dane.ns.cloudflare.com produced the authoritative answer. A resolver makes that walk silently; when you debug by hand, you have to follow the NS records yourself.

What the answer tells you and what it hides

Question Visible to any resolver? Where to find it otherwise
Which addresses the apex returns, and their TTL Yes Not needed
That the apex has no CNAME on the wire Yes, as NODATA for type CNAME Not needed
Which hostname the apex follows No Provider dashboard, API, or zone export
Whether the record is proxied or DNS-only No; Cloudflare-owned addresses are only a hint Provider dashboard
Whether the addresses come from flattening or from static A/AAAA records No; matching the target is circumstantial Provider configuration
That the target’s addresses changed Only indirectly, as new apex answers after the TTL Monitor the apex and the target together

Our capture shows the limit. Identical address sets strongly suggest that the apex follows and-guide.pages.dev, but static A and AAAA records copied from the target would look exactly the same today, and would quietly break if the platform ever renumbered. Only the configuration tells the two apart. Keep the configured target, the proxy status, and the flattening setting in infrastructure-as-code or an exported zone file, and list the apex in your public hostname inventory together with its hidden target.

How Cloudflare builds a flattened answer

These are Cloudflare’s documented rules as of this update:

  • When it happens. A CNAME at the zone apex is flattened by default on every plan. Proxied records are flattened by default as well, since they answer with Cloudflare’s anycast addresses. For other names, per-record flattening and a zone-wide “flatten all CNAMEs” setting are paid-plan features, and a CNAME whose target sits in the same zone is flattened regardless of the setting.
  • Which TTL you get. A proxied record returns Cloudflare addresses with a TTL of 300. A DNS-only record returns the target’s addresses with the lower of the target’s TTL and the CNAME’s own TTL.
  • When the target is missing. If the chain ends at a name with no A or AAAA records, the flattened answer is empty: NODATA, because there is nothing to flatten to.

Our apex returned 300 for a target that also publishes 300, which fits both TTL rules. The TTL alone cannot tell you which one applied.

The platform side has its own ordering rule. Cloudflare’s Pages documentation warns that adding the CNAME by hand, without first adding the custom domain to the Pages project, leaves the domain failing with a 522 error. DNS can be flawless while the platform rejects the host; the Cloudflare Pages custom domain guide covers that sequence.

Other ways providers solve the apex problem

Mechanism Standardized? What dig shows Notes
Cloudflare CNAME flattening No, a provider feature A and AAAA only Any hostname target; TTL rules above
Route 53 alias record No, a provider feature A or AAAA, whichever type you chose Targets limited to supported AWS resources or a record in the same hosted zone; the TTL of an AWS target can’t be set; the alias shows only in Route 53’s console or API
“ALIAS” or “ANAME” in other dashboards No; neither appears in the IANA DNS record type registry Usually synthesized A and AAAA Target rules, TTL handling, and DNSSEC behavior vary by provider
HTTPS record in AliasMode (RFC 9460) Yes, record type 65 An HTTPS record naming another host Helps only clients that look up HTTPS records; RFC 9460 expects operators to keep A and AAAA records for everyone else

The practical consequence: moving a zone between providers means re-creating the apex behavior, not copying a record. An exported “ALIAS” line may mean something different to the next provider, or nothing at all.

Debugging a flattened apex

  1. Ask your zone’s authoritative server for A and AAAA at the apex, with +norec, and check for the aa flag. If it answers NOERROR with nothing in the answer section, look at the target first: under Cloudflare’s rules, a target without addresses produces NODATA.
  2. Resolve the configured target yourself, following any delegation as we did with pages.dev, and compare the address sets.
  3. If the apex shows Cloudflare addresses and the target doesn’t, the record is proxied. That is expected, and the target is then reached only through Cloudflare’s edge.
  4. If a public resolver still shows old addresses while the authoritative answer is new, you are looking at a cache. The propagation guide shows how to read remaining TTLs.
  5. If DNS is right and the site is not, move up a layer: the platform must accept the apex as a custom domain and hold a certificate for it.

Keep verification CNAMEs unflattened

Some vendors prove domain ownership by looking up a CNAME token. Cloudflare warns that flattening all CNAMEs can break this, because the CNAME itself is no longer returned. For those records:

  • leave per-record flattening off, and review every verification record before enabling “flatten all CNAMEs”;
  • keep them DNS-only, since proxied records are flattened by default;
  • confirm with dig +short <token-name>.example.com CNAME that the answer is the vendor’s hostname, not an address.

Changing or rolling back the target

  1. Export the current configuration: target hostname, proxy status, and TTL.
  2. Add the apex to the new platform first, so it can accept the host and issue a certificate.
  3. Change the target once, then confirm the authoritative A and AAAA answers.
  4. Expect the old addresses to linger in caches for up to the old TTL (300 seconds in our case), and keep the old platform serving the domain until then.
  5. To roll back, restore the exported target rather than the addresses you last saw, which may already be stale.