move DNS to Cloudflaremove DNS to Cloudflare

Moving a domain’s DNS to Cloudflare looks like a five-minute job. Add the domain, accept the records Cloudflare finds, change two nameservers at your registrar, done. For a parked domain or a simple brochure site, it really is that easy.

For a domain that carries your email, it isn’t. I’ve been moving our company domains off the registrar’s DNS and onto Cloudflare, starting with smaller brand domains and working up to the one every staff mailbox depends on. The steps aren’t hard. What makes it risky is that the most dangerous mistakes don’t show up straight away. The website loads, the dashboard says Active, and you find out two hours later that no external email has arrived since lunch.

This guide covers the full process in the order I’d do it again, with a PowerShell script to compare the old and new DNS before you switch, and a troubleshooting section for when something goes wrong. It’s written with Microsoft 365 in mind, but the same traps apply to Google Workspace and any other mail provider.

Why move DNS to Cloudflare at all?

Cloudflare’s DNS hosting is free, quick to update, has a proper API, and makes DNSSEC a one-click job. Those were all nice to have. What actually forced our move was a website.

Our site moved behind Amazon CloudFront, which gives you a hostname to point at rather than a fixed IP address. The www record could follow it with a CNAME. The bare domain (example.com, also called the zone apex) couldn’t, because DNS doesn’t allow a CNAME at the apex alongside the NS, SOA and MX records that must live there. AWS gets around this inside Route 53, but our registrar’s DNS had no equivalent.

Cloudflare solves it with CNAME flattening. Cloudflare’s documentation says flattening happens automatically on every plan, including Free, for a CNAME at the zone apex. You create the CNAME at @, Cloudflare looks up the target itself, and the rest of the world sees normal A records. If you’re stuck with a website on CloudFront, Azure Front Door, Heroku or any similar platform at the bare domain, this alone is a good reason to move.

What actually changes (and what doesn’t)

It’s easy to blur two separate things here. Your registrar is the company you pay to hold the domain. Your DNS host is whoever answers queries for it. Often they’re the same company, so it feels like one thing.

You can move your DNS to Cloudflare without transferring the domain registration. We kept every registration exactly where it was and changed only the nameservers. Renewals, ownership details and billing carry on as before, and if something goes badly wrong, rolling back is a nameserver edit rather than a domain transfer.

Step 1: Take a full copy of your current records

When you add a domain, Cloudflare scans for existing records and offers to import them. The catch is that DNS can’t be listed. A scanner can only ask about names it already knows to try, so anything with an unusual name is missed.

If your current provider can export a BIND zone file, export it and import that into Cloudflare instead of trusting the scan. If it can’t, copy every record out of its portal by hand. It’s tedious, but it’s the only way to know nothing was left behind.

These are the records I see missed most often on a domain used for email:

  • DKIM records. For Microsoft 365 these are CNAMEs at selector1._domainkey and selector2._domainkey. Google Workspace uses a TXT record at google._domainkey.
  • The DMARC record at _dmarc.
  • autodiscover, which Outlook uses to find mailboxes.
  • enterpriseregistration and enterpriseenrollment, if you use Intune or Entra device registration.
  • Domain verification TXT records for Microsoft 365, Google, Apple, Atlassian and anything else you’ve connected.
  • SRV records for older Teams or Skype setups and VoIP systems.
  • Subdomains for VPN endpoints, remote access gateways and line-of-business apps that only IT knows about.

Step 2: Add the domain and check every imported record

Add the domain in the Cloudflare dashboard, choose the plan (Free is fine for DNS), and import your zone file. Then go through the record list line by line against your export. You’re looking for missing records, duplicates, and values that were mangled on the way in. Long TXT records such as SPF and DKIM are the usual suspects.

At the end of setup, Cloudflare assigns two nameservers, something like ada.ns.cloudflare.com and bob.ns.cloudflare.com. Note them down, but don’t change anything at the registrar yet.

Step 3: Set proxy status correctly

This is the setting that breaks email.

Every A, AAAA and CNAME record in Cloudflare is either proxied (the orange cloud) or DNS only (grey). A proxied record answers with Cloudflare’s IP addresses, and Cloudflare sits in the path of the traffic. That’s what you want for a website. Anything that isn’t web traffic will fail through it.

The MX record itself can’t be proxied, which gives a false sense of safety. The trap is the A record your MX points to. If mail.example.com is an A record and it gets proxied, your MX now leads to Cloudflare, and inbound mail goes nowhere.

After the import, check the proxy status of every A, AAAA and CNAME record. Set these to DNS only:

  • Any hostname your MX records point to.
  • autodiscover, enterpriseregistration and enterpriseenrollment.
  • VPN, remote desktop gateway, FTP and SIP hostnames.
  • Anything already behind another CDN, such as CloudFront. Running a site through two CDNs adds a layer that does nothing useful and makes problems much harder to trace.

If you’re not sure whether something is a website, set it to DNS only. You can always turn the proxy on later. Debugging a broken service you forgot existed is much harder.

Step 4: Turn off DNSSEC at your registrar

This is the step that can take a domain completely offline. If DNSSEC is on, your registrar has published a DS record that vouches for your current provider’s signing keys. Switch the nameservers while it’s still there, and resolvers that check DNSSEC will reject Cloudflare’s answers because the signatures don’t match.

Cloudflare’s setup guide lists disabling DNSSEC at the registrar as a prerequisite, and its transfer guide recommends waiting at least 24 hours after removing it before you change nameservers. If you’re not sure whether DNSSEC is on, look for a DNSSEC or DS record setting in your registrar’s portal. If one exists and has a value, remove it.

Step 5: Lower your TTLs

A day or two before the switch, drop the TTL on your important records at the old provider to around five minutes. If you find a mistake after the move, resolvers that cached the old answer will let go of it quickly.

This doesn’t make the nameserver change itself happen faster. How quickly the internet notices your new nameservers depends on TTLs set by the domain’s registry, which you don’t control. It just shortens the tail on everything else.

Step 6: Prove both providers give the same answers

Cloudflare’s assigned nameservers will answer queries for your domain as soon as you’ve added it, before you change anything at the registrar. That means you can ask both providers the same questions and compare the answers while the old one is still live.

This script does that. Build the $checks list from your export, and put in one of your old provider’s nameservers and one of the pair Cloudflare gave you:

$domain = "example.com"
$oldNs  = "ns1.oldprovider.net"
$newNs  = "ada.ns.cloudflare.com"

$checks = @(
    @{ Name = $domain;                         Type = "A"     },
    @{ Name = $domain;                         Type = "MX"    },
    @{ Name = $domain;                         Type = "TXT"   },
    @{ Name = "www.$domain";                   Type = "CNAME" },
    @{ Name = "autodiscover.$domain";          Type = "CNAME" },
    @{ Name = "selector1._domainkey.$domain";  Type = "CNAME" },
    @{ Name = "selector2._domainkey.$domain";  Type = "CNAME" },
    @{ Name = "_dmarc.$domain";                Type = "TXT"   }
)

function Get-RecordValues($Name, $Type, $Server) {
    Resolve-DnsName -Name $Name -Type $Type -Server $Server -DnsOnly -ErrorAction SilentlyContinue |
        Where-Object { $_.Type -eq $Type } |
        ForEach-Object {
            switch ($Type) {
                "A"     { $_.IPAddress }
                "CNAME" { $_.NameHost }
                "MX"    { "$($_.Preference) $($_.NameExchange)" }
                "TXT"   { $_.Strings -join "" }
            }
        } | Sort-Object
}

foreach ($c in $checks) {
    $old = (Get-RecordValues $c.Name $c.Type $oldNs) -join ", "
    $new = (Get-RecordValues $c.Name $c.Type $newNs) -join ", "
    $status = if ($old -eq $new) { "OK" } else { "DIFFERENT" }
    "{0,-10} {1,-6} {2}" -f $status, $c.Type, $c.Name
    if ($status -eq "DIFFERENT") { "           old: $old`n           new: $new" }
}

Records you’ve deliberately proxied will show as different, because Cloudflare answers with its own IPs. So will the apex if you’ve replaced an A record with a flattened CNAME. Everything else should say OK. If it doesn’t, fix it in Cloudflare and run the script again.

Step 7: Change the nameservers

At your registrar, replace the existing nameservers with the two Cloudflare assigned. Remove every old one rather than adding Cloudflare’s alongside them. Cloudflare’s troubleshooting guide is clear that the values must match exactly, and that no other nameservers should be listed.

For a while afterwards, some resolvers will still ask the old provider and some will ask Cloudflare. Both need to give the same answers, so don’t make DNS changes during this window. If something has to change, change it in both places.

Step 8: Check everything once it goes active

Cloudflare emails you and marks the domain Active once it sees the new nameservers. Then confirm the delegation from a couple of public resolvers:

Resolve-DnsName -Name example.com -Type NS -Server 1.1.1.1
Resolve-DnsName -Name example.com -Type NS -Server 8.8.8.8

Run the comparison script again. Then test email properly, not just by sending one message to a colleague:

  • Send a message in from an outside mailbox, such as a personal Gmail or Outlook.com account.
  • Send one out to an outside mailbox, open the message headers and confirm SPF, DKIM and DMARC all pass.
  • If you use Microsoft 365, run the domain health check in the admin centre as a second opinion.

Finally, turn DNSSEC back on. Enable it in Cloudflare, which gives you a new DS record, and add that at your registrar. Leave the old DNS zone untouched for at least a week in case anything is still asking it.

How long does the switch take?

Cloudflare’s own guidance is to allow up to 24 hours for the registrar to update the nameservers. In practice it’s often much quicker, but you don’t control it, so plan as though it will take the full day. That’s the main reason to do the switch outside business hours and to make sure both providers return the same answers. While it settles, half the internet could be asking one and half the other.

Troubleshooting

Email stopped arriving. Start with the proxy status of whatever your MX record points to, because that’s the usual cause. Then check the MX record exists at all, and that its priority values came across correctly. If mail arrives but lands in junk or fails DMARC, compare the SPF TXT record and the DKIM records against your export. A truncated SPF record or a missing DKIM selector is enough to do it.

The website shows “too many redirects”. This is almost always the SSL/TLS encryption mode. On Flexible, Cloudflare talks to your web server over plain HTTP. If the server redirects HTTP to HTTPS, which most do, the browser loops forever. Set the mode to Full (strict) if your server has a valid certificate. Or, if the site sits behind another CDN, set the record to DNS only.

The domain is stuck on Pending. Check three things at the registrar. Is a DS record still there? Do the nameservers exactly match the pair Cloudflare gave you? Are any old nameservers still listed next to them? One of those is nearly always the answer.

A service says your domain verification has failed. Some vendors verify ownership with a CNAME and expect to see the CNAME itself. Cloudflare notes that turning on CNAME flattening for all records can break this, because the CNAME is never returned. Leave that setting off unless you need it. Apex flattening still happens without it.

Error 1014. This means a CNAME points at a hostname in a different Cloudflare account, which Cloudflare blocks when the record is proxied. Set the record to DNS only, or ask the provider whether they can add your hostname as a custom hostname on their side.

What I’d tell anyone doing this for the first time

Don’t start with the domain that matters. We moved two smaller brand domains first. If something had gone wrong, the worst case was a marketing page offline for an hour. It also means that when you reach the domain carrying everyone’s email, the export, import, proxy review and comparison script are routine rather than new.

Keep the email domain’s switch away from any other mail changes. If you’re also changing addresses, spam filtering or mail authentication, give each one its own day. When something breaks, you want only one possible cause.

Leave a Reply

Your email address will not be published. Required fields are marked *