We were 20 minutes into a CDN cutover for a retail client back in 2021 when their checkout started throwing ERR_SSL_VERSION_OR_CIPHER_MISMATCH. The new CDN was serving a stale intermediate chain they'd forgotten to update, and browsers that had cached the old chain were fine — everyone else wasn't. It took us 47 minutes to roll back, re-issue, and purge. That outage cost them more than the entire CDN contract for the year, and it taught me that SSL migration isn't a checkbox item. It's the most fragile part of any Comprehensive CDN Migration Checklist: Every Step from Planning to Cutover you'll ever execute.
Where Certificate Continuity Actually Fails
Most teams assume certificate transfer is simple: export the cert, import it to the new CDN, flip DNS, done. If only it were that clean. In practice, what breaks isn't the certificate itself — it's the trust chain that surrounds it. Your current CDN isn't just hosting your leaf certificate; it's serving a specific intermediate bundle, negotiating TLS versions, handling OCSP stapling, and pinning cipher suites that your origin and your clients have grown accustomed to. Miss one of those pieces and you've got a partial outage that won't show up in synthetic monitoring until real users hit it.
I've seen this happen most often with wildcard and multi-SAN certificates that were originally provisioned through the old CDN's managed PKI. The private key never left their HSM, so there's nothing to export. The team discovers this two days before cutover and suddenly they're scrambling for a re-issue while the business is screaming about deadlines. That's why your CDN Vendor Evaluation Matrix: Scoring Providers on What Actually Matters needs to include a line item for certificate portability on day one, not week six. Ask your vendor: do you support bring-your-own private keys, do you support delegated DCV, and what's your process for uploading custom intermediates? If they can't answer clearly, that's a red flag.
Another quiet failure mode is TTL and SNI mismatch. If you're moving from a CDN that used a shared SAN with custom hostname support to one that requires dedicated certificates per hostname, your certificate inventory can double overnight. The HTTP Working Group Specifications don't care which CDN you're on, but browsers absolutely do when they evaluate the Subject Alternative Name list. Before you plan the transfer, you need to inventory every hostname — including those forgotten marketing microsites and API endpoints — and confirm how each will validate on the new edge.
# Audit your current chain as the client sees it - don't trust the dashboard
openssl s_client -connect www.example.com:443 -servername www.example.com -showcerts < /dev/null | \
awk '/BEGIN CERTIFICATE/,/END CERTIFICATE/' | \
while read -r cert; do echo "$cert"; done | \
openssl crl2pkcs7 -nocrl -certfile /dev/stdin | openssl pkcs7 -print_certs -text -noout | grep -E "Subject:|Issuer:|Not After :|DNS:"
# Check OCSP stapling and protocol support in one pass
echo | openssl s_client -connect www.example.com:443 -servername www.example.com -status -tlsextdebug 2>&1 | \
grep -E "OCSP response|Protocol|Cipher"
Auditing Your TLS Footprint Before You Touch Anything
You can't migrate what you haven't mapped, and I've never once seen a client's spreadsheet match reality on the first try. We always start with a passive audit. Pull certificate transparency logs, scan your DNS zones, and scrape your CDN config for every hostname with TLS enabled. Don't forget custom origins that terminate TLS themselves — like that legacy checkout service that pinned its own cert three years ago and nobody documented. One fintech I worked with had 14 active hostnames they knew about and 9 additional ones we found via CT logs, including an old `api-staging.example.com` that was still serving production traffic from a forgotten CNAME.
Once you've got the inventory, document the private key custody for each cert. This determines your entire migration path. Is the key exportable? Is it managed by the CDN (like Cloudflare or Akamai's shared certs)? Is it an Extended Validation cert that requires manual verification? Is it issued with ACME automation that you'll need to replicate? I keep a simple matrix for this, and I insist clients fill it out before we even draft the CDN RFP Template: Writing Requirements That Get Meaningful Vendor Responses for the new provider. If you wait until implementation, you're negotiating from a position of weakness.
You should also baseline your current TLS configuration. Record the supported TLS versions, cipher suites, HSTS headers, and OCSP stapling behavior as seen from multiple vantage points — not just what the CDN dashboard says. The guidance in web.dev Articles on TLS best practices is a good reference for what modern clients expect, but your job during migration is to *match* the old behavior first, then improve. Changing TLS versions and migrating CDNs in the same window is how you create an undebuggable outage. Keep the crypto identical for cutover, then tune later.
# Generate a complete inventory from Certificate Transparency
# Requires jq and crt.sh API - run for each registered domain
DOMAIN="example.com"
curl -s "https://crt.sh/?q=%25.${DOMAIN}&output=json" | jq -r '.[].name_value' | \
tr ' ' '\n' | sed 's/^\*\.//' | sort -u > ct_hostnames.txt
echo "Found $(wc -l < ct_hostnames.txt) unique hostnames in CT logs"
cat ct_hostnames.txt
# Cross-reference with live DNS to find currently active hostnames
while read -r host; do
if dig +short "$host" | grep -q .; then
expiry=$(echo | openssl s_client -connect "${host}:443" -servername "$host" 2>/dev/null | \
openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
echo "${host} | ${expiry} | ACTIVE"
fi
done < ct_hostnames.txt | sort -k3
Picking Your Migration Path: Re-issue, Export, or BYO
There are really only three ways to get your certificates onto the new CDN, and none of them is universally right. Private key export sounds easiest, but it's often impossible with managed certs and it's a security anti-pattern if you don't handle the key material correctly. If you do export, you must treat that PFX or PEM bundle like a production secret — encrypted at rest, transferred over a secure channel, and deleted from any intermediate workstation. I still cringe thinking about a client who emailed their wildcard private key as an unencrypted attachment in 2018. We had to revoke and re-issue everything.
Re-issuing is cleaner from a security standpoint but it introduces validation risk. You'll need to complete Domain Control Validation (DCV) again, which means coordinating DNS TXT records or HTTP file challenges for every SAN on the cert. For a 25-SAN certificate, that's 25 validation points that can fail if your DNS provider rate-limits or if your old CDN is still answering the HTTP challenge path. This is where cert continuity planning matters most. My rule is to have the new certificates issued and deployed to the new CDN at least 7 days before cutover, with automated checks that verify the chain from outside both CDNs. That gives you time to catch intermediates that don't chain correctly or CAA records that block the new CA.
The third option — Bring Your Own Certificate with delegated validation or CNAME-based DCV — is increasingly supported by major CDNs and it's my preferred approach for large portfolios. You keep your own ACME client or CA relationship and delegate just the validation record (like `_acme-challenge.example.com` via CNAME) to the new CDN. The CDN handles auto-renewal without ever holding your long-term private key for longer than necessary. It's more setup up front, but it eliminates vendor lock-in for your PKI and keeps you in control of the certificate lifecycle. Whichever path you choose, don't forget to plan for dual-serving: you'll need both CDNs to serve valid, trusted certificates during the DNS transition window, which can last 48-72 hours due to resolver caching.
| Migration Method | Validation Time | Dual-Serving Window | Private Key Exposure | Best For |
|---|---|---|---|---|
| Private Key Export (PFX/PEM) | 0-2 hours (no re-validation) | 2-4 hours | High - key traverses systems | Single wildcard cert, urgent cutover |
| Re-issue via DNS/HTTP DCV | 4-24 hours (per SAN) | 48-72 hours | Low - new key pair generated | Multi-SAN certs, security-sensitive orgs |
| CNAME Delegated DCV / BYO ACME | 15-60 minutes (automated) | 72+ hours (continuous renewal) | Minimal - CDN holds short-lived key | Large hostname portfolios, long-term control |
| CDN-Managed Auto-Provisioned | 5-15 minutes | 24-48 hours | None - CA + CDN fully managed | Standard domains, low compliance overhead |
Staging, Validating, and Switching: The 48-Hour Implementation Window
Don't cut DNS on day one. That's how you turn a 5-minute migration into a 6-hour incident. The cleanest migrations I've run use a 48-hour staged window where both CDNs serve valid certificates simultaneously. You'll want to drop your DNS TTL to 60 seconds at least 48 hours before cutover — if you're still sitting on a 3600 or 86400 second TTL, you're not ready to move. Once the new edge is provisioned, upload or re-issue the cert there first and leave the old CDN completely untouched. We've seen teams try to save $300 on a duplicate cert and end up invalidating the original private key in the process.
Validation has to happen at the edge, not just in the dashboard. Most CDN control panels will show a green checkmark even if the intermediate chain is broken or OCSP stapling isn't working. Hit the new edge directly using a hosts file override or the provider's staging hostname — don't rely on curl to the origin. Check the full chain, SAN coverage, and expiration on every edge PoP that will serve production traffic. If you're migrating 15+ SANs or a wildcard plus 40 alternate names, automate this. A single missing SAN will pass 95% of your synthetic checks and still break checkout for that one legacy subdomain your finance team forgot to mention. For complex setups, it's worth running a formal CDN Proof of Concept Planning: Designing a PoC That Answers Real Questions on the new platform before you commit to the cert strategy.
When you're ready to switch, don't do a big-bang DNS flip if you can avoid it. Weighted routing or a 10% -> 50% -> 100% shift over 4-6 hours gives you time to catch TLS handshake errors in real logs. Monitor handshake failure rate, not just 5xx. A healthy cutover should stay under 0.02% TLS errors; if you spike above 0.1% for more than 2 minutes, roll back — that's why you kept that 60-second TTL. This phased approach is detailed in our CDN Traffic Cutover Strategy: Migrating Without Downtime or Data Loss, and it's saved us more than once when a client's legacy Android app didn't trust the new intermediate.
# Validate new CDN edge before DNS cutover - run from jump box
# Checks chain, OCSP stapling, and SANs directly against edge IPs
EDGE_IPS=("104.16.12.34" "104.16.13.34" "162.159.140.12")
DOMAIN="www.example.com"
for IP in "${EDGE_IPS[@]}"; do
echo "=== Testing edge $IP ==="
# Full chain + dates + issuer
echo | openssl s_client -connect $IP:443 -servername $DOMAIN -showcerts 2>/dev/null \
| awk '/BEGIN CERT/{p=1} p; /END CERT/{p=0}' \
| openssl x509 -noout -dates -issuer -ext subjectAltName
# OCSP stapling check - must return "OCSP Response Status: successful"
echo | openssl s_client -connect $IP:443 -servername $DOMAIN -status 2>/dev/null \
| grep -A 8 "OCSP response"
# Real handshake via --resolve (bypasses DNS)
curl -Ivs --resolve "$DOMAIN:443:$IP" "https://$DOMAIN/healthz" 2>&1 | grep -E "SSL certificate|handshake|HTTP/"
echo ""
done
# Fail if any cert expires in <30 days
openssl s_client -connect ${EDGE_IPS[0]}:443 -servername $DOMAIN 2>/dev/null \
| openssl x509 -noout -checkend 2592000 || echo "WARNING: Cert expires within 30 days!"
Edge Cases That'll Bite You: HSTS, Pinning, and Origin Pull Failures
If your domain is HSTS preloaded or you've set `max-age=31536000; includeSubDomains; preload`, there's no graceful fallback to HTTP. The browser will hard-fail on any certificate error, and users won't get a click-through warning. I've watched a migration where the new CDN served a valid cert but forgot to enable the intermediate, and Chrome's HSTS cache turned a 2-minute fix into a 45-minute outage for 30% of returning users. Before migration, check `chrome://net-internals/#hsts` and the hstspreload.org status. If you're preloaded, you need 100% cert parity before you move a single DNS record, and you should keep the old CDN's cert valid for at least 7 days post-cutover as a safety net.
The other silent killers are certificate pinning and origin pull mTLS. If your mobile apps pinned the old intermediate or leaf — and about 1 in 8 enterprise apps we've audited still do — they'll reject the new CDN's perfectly valid cert even though browsers love it. Same story with origin authentication: if your origin is configured to only accept client certificates from your old CDN's CA for pull requests, the new CDN will get 526 errors all day. You'll need to add the new CDN's origin CA to your origin's trust store and run dual-pull for 24-48 hours. Test this with a real staged hostname, not just by whitelisting the new CDN's IPs. And don't forget OCSP stapling — if the new provider doesn't staple or their OCSP responder has 800ms latency, you'll see a 200-400ms TTFB regression on cold handshakes, which our CDN Pilot Testing Methodology: Metrics, Duration, and Success Criteria catches in the first hour of real user monitoring.
Finally, watch Certificate Transparency logs. When you re-issue instead of exporting, the new cert appears in CT logs within 2-4 hours, and some legacy monitoring tools will alert on "unexpected certificate issuance" and page your SOC at 2 AM. Give your security team a heads-up with the new cert's SHA-256 fingerprint and issuer. If you're using Let's Encrypt with a 90-day lifetime and auto-renewal on the new CDN, make sure you disable renewal on the old provider after cutover — we've seen dual renewals cause rate-limit hits (50 certs per registered domain per week) that block emergency re-issues.
Frequently Asked Questions
Can I serve the same certificate from two CDNs at once during migration?
Yes, and you should for at least 48-72 hours. Most CAs allow you to deploy the same cert and private key on multiple platforms simultaneously — you're not violating the license unless your CA's terms specifically forbid it, which is rare outside of some legacy Extended Validation products. The only hard limit is if you're using a CDN-managed certificate where you don't have access to the private key; then you can't export it and you'll need to re-issue a second cert for the new CDN. In that case, just run two valid certs in parallel.
Should I use DNS-01 or HTTP-01 validation when re-issuing for the new CDN?
Use DNS-01 for any migration involving a CDN. HTTP-01 validation will fail or flap if traffic is still weighted to the old CDN, and it requires the validation token to be served from the edge — which you don't control consistently mid-migration. With DNS-01, you add a single `_acme-challenge` TXT record and both CDNs can validate independently. It takes 60-120 seconds to propagate if your DNS TTL is low, and it's far less brittle than trying to coordinate file-based validation across two providers.
How long should I keep the old CDN certificate after cutover?
Keep it valid and deployed for at least 7 days, ideally 14. You'll need it for instant rollback if handshake errors spike, and for serving stale DNS cache — about 3-5% of resolvers will still hit the old edge 24 hours after you flip, and 0.5% can linger for 48+ hours if they ignore your TTL. Don't revoke it immediately either; revocation via OCSP can actually break rollback if clients have cached the revoked status. Just let it expire naturally and decommission the old distribution after 2 weeks with zero errors.
Will migrating CDNs break Let's Encrypt auto-renewal?
It will if you don't update the renewal hooks. Let's Encrypt certs expire every 90 days and most CDN integrations renew at 30 days before expiry. If you point DNS to the new CDN but leave the old CDN's auto-renewal active, the old provider will fail its HTTP-01 challenge and start emailing expiration warnings at day 20. Worse, if both try to renew via DNS-01 with the same TXT record, one will overwrite the other. Disable auto-renewal on the source CDN the moment you confirm 100% traffic on the new edge, and verify the new CDN's renewal job succeeds at least once before you call the migration done.