The Plan Was Simple
Point some DNS records at Cloudflare Pages. Site goes live on the real domain. Five-minute job.
That was the plan for my consulting site after migrating from Squarespace to Hugo. The site was already deployed to Cloudflare Pages, happily serving traffic at its *.pages.dev subdomain. All that remained was connecting the production domain. I had done this kind of thing a hundred times: add a CNAME here, maybe an ALIAS record there, wait for propagation, done.
Except Cloudflare Pages doesn’t work that way for apex domains. And nobody told me until I was already in the dashboard clicking buttons.
The Apex Domain Problem
Here is the thing about Cloudflare Pages custom domains: subdomains work fine with external DNS. You can point www.yourdomain.com at your Pages project with a standard CNAME record managed anywhere. But the bare domain (yourdomain.com) requires your nameservers to be at Cloudflare.
Why? Because DNS doesn’t allow CNAME records at the zone apex. The apex needs A records (or AAAA), and those need static IPs. Cloudflare Pages doesn’t give you static IPs; it uses anycast addresses that can change. Cloudflare’s solution is CNAME flattening: you store a CNAME internally, and their nameservers resolve it to A records at query time. Clever, but it only works when Cloudflare’s nameservers are authoritative for your zone.
This means “add a custom domain” actually means “migrate your entire DNS to Cloudflare.” For a domain with nothing but web hosting records, that’s trivial. For a domain with Google Workspace email, SPF, DMARC, domain verification records for Google and Facebook, and a DKIM CNAME from a service you forgot you trialed? That’s a different conversation.
I should have seen this coming. I’ve worked with Akamai, where the same pattern exists: CDN products that front traffic through anycast have been solving the apex domain problem with proprietary DNS tricks for years. My brain defaulted to textbook DNS instead of remembering how these products actually work. Worse, even the textbook default was an oversight; classic DNS has no mechanism for pointing an apex at a dynamic service without a static IP. I knew both of these things and activated neither.
This was Claude’s implementation plan, and I followed it without applying the experience I had. The research said “add a custom domain,” and I took it at face value. It’s the same lesson from the Own Your Stack series: Claude doesn’t have scar tissue from DNS migrations that went sideways at 2 AM. It doesn’t know that “just add a record” is never just adding a record when you have email authentication, domain verification, and a registrar that isn’t your CDN. That judgment is your job. This time, I didn’t do mine until I was already in the dashboard.
The Inventory Before You Touch Anything
Before changing nameservers, I needed a complete picture of every DNS record that mattered. The approach: screenshot the current provider’s DNS panel, then validate every record with dig queries against the authoritative nameservers.
This cross-referencing turned out to be critical. My domain was registered at Squarespace, but the nameservers were actually Google Domains (legacy from Google’s domain business being acquired by Squarespace). Records were managed in Squarespace’s UI but served by Google’s infrastructure. One record (a DKIM CNAME from a bulk email trial) showed up in the Squarespace panel but returned nothing from public DNS. Without the validation step, I would have migrated a ghost record and never noticed.
The records that had to survive the migration:
- MX record pointing to Google Workspace
- SPF TXT record for email authentication
- DMARC policy record
- Google Search Console verification TXT
- Facebook domain verification TXT
Everything else (the Squarespace hosting A record, www CNAME, and a domain connect CNAME) was getting replaced or dropped.
The Migration Sequence
Order matters here because email can’t go down.
First: add the domain as a zone in Cloudflare’s dashboard (free plan). Cloudflare scans your existing DNS and imports what it finds. This is where you validate. Compare every imported record against your inventory. Cloudflare’s scan caught all five of my critical records, which saved manual re-entry, but I wouldn’t have trusted it without checking.
Second: delete the old hosting records from Cloudflare’s DNS panel. The Squarespace A record and www CNAME are dead weight; they’ll just cause confusion if left in place.
Third: change nameservers at your registrar. This is the point of no return. Once the new nameservers propagate, Cloudflare owns your DNS resolution. If you missed a record, you’ll find out when something breaks.
Fourth: add the custom domain in the Cloudflare Pages project. Pages creates the CNAME (with flattening) automatically. Add a www CNAME manually pointing to the same Pages subdomain.
Fifth: set up redirect rules. I wanted the apex as canonical with www redirecting to it, plus HTTP-to-HTTPS everywhere. Cloudflare’s redirect rules use wildcard pattern matching; two rules handled all four permutations (http apex, http www, https www all redirect to https apex).
What Surprised Me
Propagation was fast. My mental model spans the full range here: I remember when 48 hours was the minimum you’d quote for global DNS propagation, and I’ve watched Route 53 changes go global in under ten minutes. I expected Cloudflare to land somewhere in between, nowhere near AWS speeds but better than the bad old days. Google’s public DNS (8.8.8.8) and Cloudflare’s own resolver (1.1.1.1) picked up the new nameservers within 20 minutes. Not Route 53 fast, but close enough to be genuinely impressive.
The Pages custom domain setup worked while the zone was still “pending” activation. I expected to have to wait, but Cloudflare let me add the domain and create the DNS records before nameserver propagation completed. Everything was ready the moment the zone went active.
CNAME flattening is invisible to the outside world. External resolvers see normal A records; they have no idea a CNAME is involved. This is the right kind of infrastructure magic: it solves a real protocol limitation without leaking abstraction.
The Takeaway
If you’re planning to use Cloudflare Pages with a custom apex domain, budget for a full DNS migration, not just a record change. Inventory every DNS record before you start, validate with dig against the actual nameservers (not just the registrar’s UI), and change nameservers only after you’ve confirmed every record exists in Cloudflare’s panel.
The whole process took about an hour of active work, plus propagation time. Not painful once I had the right expectations. The pain was discovering the requirement mid-cutover instead of during planning, because I let a confident implementation plan substitute for the compulsory point-by-point infrastructure review I would have done five years ago.
That’s the recurring lesson from this entire migration: AI-assisted planning is fast, coherent, and persuasive. It’s also working from documentation and common patterns, not from hard-won experience and caution that comes with being on the hook to address the repercussions of an incomplete plan at 11 PM on a Friday. When you work with AI, there is a clear separation of duties. Your job isn’t to follow the plan. Your job is to validate it against everything you know that the plan doesn’t. The moment you stop doing that, you’re not collaborating with the AI; you’re delegating your judgment to it.
This post is a companion to the Own Your Stack series. The DNS cutover happened alongside the baseline SEO work covered in Part 3. The series continues with Part 4: Content SEO.
I help organizations navigate infrastructure decisions like this one, from cloud architecture to platform migrations. If your team is facing a move that’s more complicated than it looks, let’s talk.