DNSCove

DNSCove guide

Migrating a zone from Route 53

DNSCove imports a Route 53 hosted zone in a single call and gives you a zero-downtime cutover: your zone starts serving on DNSCove's nameservers before you change delegation, so there's never a window where the domain resolves to nothing.

The whole migration is four steps:

  1. Export the hosted zone from Route 53.
  2. Import it into DNSCove (one API call — your AWS keys never leave your shell).
  3. Verify ownership with a TXT record so the zone goes live.
  4. Cut over your nameservers, confirm parity, and delete the old zone.

You can also do this from the console with the one-button Route 53 import; this guide shows the API path so it scripts cleanly.

Before you start

export DNSCOVE=https://api.dnscove.com
export TOKEN=dnsc_…                 # tenant-admin token
export HOSTED_ZONE_ID=Z0123456789ABCDEFGHIJ
auth="Authorization: Bearer $TOKEN"

1. Export the hosted zone

DNSCove imports the exact JSON that list-resource-record-sets produces — no transformation needed:

aws route53 list-resource-record-sets \
  --hosted-zone-id "$HOSTED_ZONE_ID" \
  --output json > zone.json

2. Import it into DNSCove

The import endpoint takes the raw Route 53 JSON wrapped in a json field. Your AWS credentials are not sent to DNSCove — you export locally and post the result.

curl -fsS -X POST "$DNSCOVE/api/import/route53" -H "$auth" \
  -d "$(jq -Rs '{json: .}' zone.json)"
{
  "zone": { "id": "Z1a2b3c4d5e6f70", "origin": "example.com.", "status": "PENDING_VERIFICATION" },
  "imported": 24,
  "skipped": [
    { "name": "old.example.com.", "type": "ALIAS", "reason": "alias target legacy-elb… does not resolve: no such host" }
  ],
  "ns": ["ns1.dnscove.com.", "ns2.dnscove.org."],
  "verification": {
    "record": "_dnscove-challenge.example.com.",
    "type": "TXT",
    "value": "dnscove-site-verification=Z1a2b3c4d5e6f70"
  }
}

What happened:

Route 53's own NS and SOA at the apex are not imported — DNSCove manages those for you and assigns ns1.dnscove.com / ns2.dnscove.org.

3. Verify ownership — the zone goes live here

Publish the verification TXT on your current DNS (still Route 53 at this point), so DNSCove can confirm you control the domain:

export ZONE=Z1a2b3c4d5e6f70
cat > verify-rr.json <<'JSON'
{ "Changes": [{ "Action": "UPSERT", "ResourceRecordSet": {
  "Name": "_dnscove-challenge.example.com.", "Type": "TXT", "TTL": 60,
  "ResourceRecords": [{ "Value": "\"dnscove-site-verification=Z1a2b3c4d5e6f70\"" }]
}}]}
JSON
aws route53 change-resource-record-sets \
  --hosted-zone-id "$HOSTED_ZONE_ID" --change-batch file://verify-rr.json

Once that TXT is visible in public DNS, verify:

curl -fsS -X POST "$DNSCOVE/api/zones/$ZONE/verify" -H "$auth"
{ "status": "ACTIVE", "verified": true, "served": true }

The zone is now ACTIVE and answered by ns1.dnscove.com / ns2.dnscove.org — while your nameservers still point at Route 53. Both providers now serve the same records. (If verified comes back false, the response repeats the exact verification record to publish and the TXT lookup it saw — give DNS a minute to propagate and retry.)

4. Cut over and confirm

Because DNSCove already serves identical answers, switching nameservers is seamless.

a. Check parity — confirm DNSCove matches what's live before you touch delegation:

curl -fsS "$DNSCOVE/api/zones/$ZONE/parity" -H "$auth"
{ "parity": { "matches": true, "checked": 24, "mismatched": 0 }, "safe_to_delete": true }

b. Flip the nameservers at your registrar (not in Route 53) to:

ns1.dnscove.com
ns2.dnscove.org

c. Wait out the old NS TTL, re-run the parity check, and once resolvers have moved over, delete the Route 53 hosted zone. Remove the _dnscove-challenge TXT whenever you like — DNSCove doesn't re-check it after activation.

Notes