Migrate DNS from NS1 to Amazon Route 53
Export and convert your DNS zones, check the answers on both providers, and switch nameservers with NS1 kept ready for rollback.
From IBM NS1 Connect to Amazon Route 53 · Published 2026-10-06
Before you commit
- Hands-on effort
- 1–3 days of hands-on work; more for traffic steering
- Elapsed time
- Allow DNSSEC and delegation TTLs, then keep NS1 serving for at least a week after cutover.
- Examples cover
- Python 3 · AWS CLI v2
- Content review
- 2026-10-09
- Integration testing
- Not recorded. Rehearse the commands and rollback on staging.
Prerequisites
- Read-only NS1 API access, Route 53 permissions, and access to the registrar and contract terms.
- A record inventory, decisions for traffic steering and a planned DNS-change freeze.
Don’t migrate yet if…
- You cannot replace required NS1 traffic steering or keep both providers consistent during propagation.
- You have not planned the DNSSEC DS-record transition or cancellation notice.
NS1 (now IBM NS1 Connect) offers self-serve plans and enterprise contracts. Route 53 charges per hosted zone and per million queries, with no contract. If you mainly use plain DNS records, compare that usage-based bill with what you pay today. Try your zone count and query volume in the calculator.
Before changing nameservers, decide how to replace any NS1 filter chains, handle DNSSEC and cancel your contract. The export script cannot do those parts for you.
0. Before you start
- Check your renewal notice period now. Enterprise DNS contracts often auto-renew unless you give notice 30–90 days ahead. Do this first, even if the migration slips.
- Pull a month of query volume from the NS1 portal, plus your zone count. These are the inputs for the calculator and the Route 53 estimate.
- List features beyond plain records: filter chains (geo, failover, weighted, shuffle), monitoring jobs, linked records/zones, DNSSEC and secondary zones. Decide how to replace each one before importing.
1. Create the hosted zone
aws route53 create-hosted-zone --name example.com --caller-reference "$(date +%s)"
Note the Id (Z0123…) and the four NameServers in the output. If you have many zones and want the same four nameservers on all of them, first create a reusable delegation set (aws route53 create-reusable-delegation-set --caller-reference …) and pass its ID to create-hosted-zone with --delegation-set-id.
2. Export and convert
Download ns1-to-route53.py (Python 3 standard library only, read it first) and run it with a read-only NS1 API key:
NS1_API_KEY=... python3 ns1-to-route53.py example.com
# 214 record sets converted, 3 need manual work -> example.com-route53/
# MANUAL api.example.com A: traffic steering: up, geotarget_country, select_first_n
The script skips SOA and apex NS records (Route 53 creates its own). It quotes and splits TXT strings at the DNS byte limit, and batches the output with headroom for Route 53’s request limits. Oversized individual record sets need manual work. It refuses to overwrite a previous export: if you repeat the export, pass a fresh directory as the second argument so stale batches cannot be imported.
It does not convert records with filter chains, linked records, or ALIAS records. It lists them in manual.txt, because translating them silently would change how they behave.
3. Rebuild the manual records
| NS1 feature | Route 53 equivalent |
|---|---|
up filter + monitoring job |
Failover routing policy + Route 53 health check |
geotarget_country / geofence_regional |
Geolocation or geoproximity routing policy |
weighted_shuffle |
Weighted routing policy |
Latency-based steering (pulsar etc.) |
Latency routing policy (AWS-region based, not RUM-based) |
| ALIAS at the apex | Alias record if the target is in AWS (CloudFront, ELB, S3…); otherwise A/AAAA records |
| Linked record | Alias record pointing to the target record in the same hosted zone (works at the apex), or a duplicate record |
Rebuild and test each of these records before cutover. Health checks are billed per check per month, so add them to your estimate.
4. Import
for f in example.com-route53/batch-*.json; do
aws route53 change-resource-record-sets --hosted-zone-id Z0123456789 --change-batch "file://$f"
done
5. Verify, record by record
Download dns-diff.sh. It queries every record against both providers’ authoritative nameservers and prints any differences:
./dns-diff.sh example.com-route53/records.txt dns1.p01.nsone.net ns-123.awsdns-45.com
Use one of your NS1 nameservers and one from step 1. Fix differences until it prints All records match. The script reports failed, NXDOMAIN and empty answers as errors, not matches.
records.txt also lists the records from manual.txt. Replace each ALIAS entry with the types you rebuilt (usually A and AAAA) before running it. TTLs aren’t compared, because the converter copies them unchanged. A matching answer from one resolver location says nothing about traffic-steered records, so test their routing and failover separately.
6. Cut over
- DNSSEC: if the zone is signed at NS1, remove the DS record at your registrar and wait at least the DS record’s TTL (one day for
.com) before changing nameservers. Skipping this makes the domain unresolvable for validating resolvers. You’ll re-enable DNSSEC on Route 53 afterwards. - Freeze DNS changes. Resolvers cache the old delegation for up to the parent zone’s NS TTL (two days for
.com), so both providers must serve the same answers during that window. If you must change something, change it in both. - Update the nameservers at your registrar to the four Route 53 nameservers.
- Watch it propagate:
dig +trace example.com, and query volume in Route 53’s CloudWatchDNSQueriesmetric.
7. Rollback plan
Keep NS1 serving for at least a week and apply any record changes to both providers. To roll back, restore the NS1 nameservers at the registrar. Rollback is not instant, because resolvers keep the Route 53 delegation until their cached NS records expire, and it is only clean if both copies stayed identical. If you have already enabled DNSSEC on Route 53, fix the DS record at the registrar first: a DS record for the wrong provider makes the zone fail validation.
8. Clean up
- Re-enable DNSSEC on Route 53: create a key-signing key from an asymmetric
ECC_NIST_P256KMS key inus-east-1(aws route53 create-key-signing-key), runaws route53 enable-hosted-zone-dnssec, then publish the DS record fromaws route53 get-dnssecat the registrar. - After a quiet week, delete the NS1 zones and send the contract termination notice, in writing and per your contract’s terms.
- Optional: import the zone into Terraform or OpenTofu so the next migration is a config change.
Many zones?
GET https://api.nsone.net/v1/zones lists every zone, so you can loop the steps above over it. Cut over in batches by risk: parked and marketing domains first, the primary domain last.
Found a command or version mismatch? Report a correction with the version and steps to reproduce it. Remove secrets and customer data first.