Use an A record when you are handed an IPv4 address that you or your team will keep running. Use a CNAME when a platform hands you a hostname, because the platform can then move its addresses without asking you. The zone apex is the one place a CNAME is not allowed, and our own domain shows what providers do instead.
Start from what you were given
| You were given | Publish | Who updates the addresses later |
|---|---|---|
| An IPv4 address you operate (a VPS, your own load balancer) | A, plus AAAA if it has IPv6 |
You, by editing the record |
| A hostname from a hosting platform, for a subdomain | CNAME to that hostname |
The platform, behind its hostname |
A hostname from a platform, for the apex (example.com) |
Your DNS provider’s flattening or alias feature, or addresses the platform documents for apex use | The platform, or you if you publish its addresses |
| A hostname, but the same name also needs MX or TXT records | Not a CNAME: ask for addresses or use another name | Depends on the choice |
| A request to send visitors to a different URL | An HTTP redirect | Not a DNS decision |
Don’t resolve a platform hostname once and paste the addresses into an A record. Those addresses belong to the platform, which can change them whenever it needs to; publish addresses directly only when the platform documents them for that purpose. If the setup instructions don’t say which record to use, ask. A guessed record works until the day it quietly doesn’t.
Reading a dig answer, column by column
Live capture, 26 September 2026. Asking our ISP’s default resolver (from a workstation in South Korea) for www.python.org, a name that aliases a Fastly CDN hostname:
dig +nocmd www.python.org A +noall +answer
www.python.org. 274659 IN CNAME dualstack.python.map.fastly.net.
dualstack.python.map.fastly.net. 50 IN A 151.101.64.223
dualstack.python.map.fastly.net. 50 IN A 151.101.128.223
dualstack.python.map.fastly.net. 50 IN A 151.101.192.223
dualstack.python.map.fastly.net. 50 IN A 151.101.0.223
+noall +answer prints only the answer section, and +nocmd hides the version banner that older builds such as macOS’s DiG 9.10.6 print anyway. Every line has five fields:
| Field | In the first line | Meaning |
|---|---|---|
| Owner name | www.python.org. |
The name the line describes; the trailing dot marks it as fully qualified |
| TTL | 274659 |
Seconds this resolver may keep serving the line from its cache |
| Class | IN |
Internet, the only class you will meet in practice |
| Type | CNAME |
The kind of data that follows (A on the other lines) |
| Data | dualstack.python.map.fastly.net. |
Another name for a CNAME, an IPv4 address for an A record |
We asked for type A and got a CNAME first. The resolver found the alias, looked up its target, and returned both steps in one answer.
The TTLs are the interesting part.
Live capture, 26 September 2026. One of python.org’s own name servers, asked directly a few minutes earlier, publishes the alias for a full week:
$ dig +nocmd @ns-981.awsdns-58.net www.python.org CNAME +norec +noall +answer
www.python.org. 604800 IN CNAME dualstack.python.map.fastly.net.
The Fastly addresses, by contrast, came back with a TTL of 60 seconds or less in every query we made that evening. python.org rarely touches its alias, while Fastly can change the addresses behind it and resolvers will pick that up within a minute. Neither operator has to edit the other’s zone. That division of labor is what a CNAME buys you.
A plain A record: the address is yours to maintain
Live capture, 26 September 2026. The same resolver, asked for dns.google, the name Google publishes for its public resolver addresses:
dig +nocmd dns.google A +noall +answer
dns.google. 102 IN A 8.8.4.4
dns.google. 102 IN A 8.8.8.8
There is no second name to follow. The answer is final, and only whoever runs the dns.google zone can change it. That is the right shape when the address is yours, such as a VPS or a load balancer you operate, and the wrong one when it belongs to someone else’s fleet.
Two differences are easy to miss:
- An A record answers only A queries. IPv6 needs its own AAAA record at the same name. Publish only an A record and IPv6-only clients get nothing.
- A CNAME aliases the whole name. As Route 53’s documentation points out, a CNAME redirects queries whatever record type they ask for. The alias therefore follows the target’s AAAA records too, and it cannot carry TXT or MX records of its own.
In zone-file form:
vps.example.com. 3600 IN A 203.0.113.42
vps.example.com. 3600 IN AAAA 2001:db8::42
docs.example.com. 3600 IN CNAME tenant.hosting.example.
Why a CNAME cannot share its name
RFC 1034 set the rule early: “If a CNAME RR is present at a node, no other data should be present.” RFC 2181 (section 10.1) made it absolute: apart from DNSSEC records, an alias holds nothing else. Two consequences settle many decisions for you:
- No CNAME at the apex. The top name of every zone must hold SOA and NS records, so a CNAME there would break the rule. Route 53, for one, refuses to create a CNAME with the same name as the hosted zone.
- No CNAME on a name that already has records. If
docs.example.comholds a TXT verification token or MX records, it cannot also be a CNAME. List what the name holds before you convert it.
Our apex: a Pages hostname served without a CNAME
and.guide is served by the Cloudflare Pages project and-guide, whose platform hostname is and-guide.pages.dev. For a subdomain, Pages tells you to add a CNAME to that hostname. For an apex, its documentation requires the zone to use Cloudflare’s nameservers, and Cloudflare then creates the CNAME record itself.
Live capture, 26 September 2026. The apex and the Pages hostname, through the same default resolver:
$ dig +nocmd and.guide A +noall +answer
and.guide. 300 IN A 172.66.44.244
and.guide. 300 IN A 172.66.47.12
$ dig +nocmd and.guide AAAA +noall +answer
and.guide. 300 IN AAAA 2606:4700:310c::ac42:2cf4
and.guide. 300 IN AAAA 2606:4700:310c::ac42:2f0c
$ dig +nocmd and-guide.pages.dev A +noall +answer
and-guide.pages.dev. 229 IN A 172.66.44.244
and-guide.pages.dev. 229 IN A 172.66.47.12
$ dig +nocmd and-guide.pages.dev AAAA +noall +answer
and-guide.pages.dev. 300 IN AAAA 2606:4700:310c::ac42:2f0c
and-guide.pages.dev. 300 IN AAAA 2606:4700:310c::ac42:2cf4
Live capture, 26 September 2026. The same resolver, asked for a CNAME at the apex a few minutes later:
$ dig +nocmd and.guide CNAME +noall +comments +authority
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14532
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; AUTHORITY SECTION:
and.guide. 1800 IN SOA frida.ns.cloudflare.com. dns.cloudflare.com. 2414193944 10000 2400 604800 1800
What to notice:
- The apex answers with A and AAAA records, and they are the same two IPv4 and two IPv6 addresses that
and-guide.pages.devreturns. Record order varies between answers; the sets match. - There is no CNAME on the wire.
status: NOERRORwithANSWER: 0means the name exists but holds no record of that type (a NODATA answer), and the SOA record in the authority section is how the server says so. - The Pages hostname’s A records show 229 rather than 300 because this resolver had cached them 71 seconds earlier. The apex’s 300 was a fresh fetch.
This is CNAME flattening, which Cloudflare applies by default on every plan when the apex holds a CNAME: its authoritative servers follow the alias themselves and return the addresses at the end of it. The apex follows the platform hostname and remains valid DNS. The CNAME flattening guide shows what a flattened answer hides and how Cloudflare sets its TTL.
Live capture, 26 September 2026. The www name, in the same run as the apex queries, shows the other way Cloudflare hides aliases:
$ dig +nocmd www.and.guide A +noall +answer
www.and.guide. 300 IN A 172.67.138.236
www.and.guide. 300 IN A 104.21.70.196
www.and.guide exists only to redirect visitors to the apex, and it is proxied through Cloudflare. For proxied records, Cloudflare answers with its own anycast addresses no matter what the record holds in the dashboard, so on a Cloudflare zone dig never reveals the CNAME behind a proxied name. The Cloudflare DNS setup guide explains proxy status in detail.
Apex options are provider features, not record types
If your DNS is hosted elsewhere, the apex problem has different answers:
- Route 53 alias records answer as A or AAAA, can point only at supported AWS resources or another record in the same hosted zone, and take their TTL from the target instead of letting you set one. The alias itself is visible only in Route 53’s console or API.
- “ALIAS” or “ANAME” records in other DNS dashboards are provider-side behavior with provider-specific rules. Check which targets and TTLs your provider documents before relying on one.
- Addresses a platform documents for apex use can go into ordinary A and AAAA records. You then own the job of updating them if the platform announces a change.
A CNAME never changes the URL
With a CNAME, the browser still asks for the original hostname; DNS only decides where it connects. The destination therefore has to accept that hostname in the Host header, present a certificate that covers it, and build redirects and callback URLs from it. If you want the address bar to change, as it does when www.and.guide sends visitors to https://and.guide/, you need an HTTP redirect at the server or edge. The www versus apex guide covers choosing and enforcing a canonical host.
Checking the record you published
- Ask one of your zone’s authoritative servers for the exact type you created, with recursion off:
dig @<your-nameserver> docs.example.com CNAME +norec. Look for theaaflag in the header. - Ask a public resolver for A and AAAA, and confirm the chain ends in addresses.
- Resolve the target on its own. An empty answer means the alias leads nowhere.
- Compare two resolvers. The DNS lookup tool queries Cloudflare and Google side by side and shows their TTLs.
- Only then test HTTPS for the public hostname, as described in the subdomain setup guide.