Exporting AWS Route 53 Hosted Zone Records: CLI & API Methods for Backup


2 views

Unlike some AWS services that provide one-click export options, Route 53 doesn't offer a direct "Export" button in the console for hosted zones. This creates challenges when you need to:

  • Migrate DNS configurations between accounts
  • Maintain version-controlled backups
  • Share zone configurations with team members

Method 1: Using AWS CLI

The most efficient way is using aws route53 list-resource-record-sets:

aws route53 list-resource-record-sets \
    --hosted-zone-id /hostedzone/Z1PA6795UKMFR9 \
    --output json > route53_backup.json

Method 2: AWS SDK Programmatic Export

Python example using Boto3:

import boto3
import json

route53 = boto3.client('route53')

def export_zone(zone_id, output_file):
    records = route53.list_resource_record_sets(
        HostedZoneId=zone_id
    )
    with open(output_file, 'w') as f:
        json.dump(records['ResourceRecordSets'], f, indent=2)

export_zone('Z1PA6795UKMFR9', 'dns_backup.json')

Method 3: DNS Zone File Format

For compatibility with other DNS systems, convert to standard zone file format:

aws route53 list-resource-record-sets \
    --hosted-zone-id Z1PA6795UKMFR9 \
    --query "ResourceRecordSets[*].[Name,Type,TTL,ResourceRecords[].Value]" \
    --output text | \
awk '{print $1 " " $2 " " $3 " " $4}' > zonefile.txt
  • Handle pagination for zones with >100 records
  • Include comments/timestamps in exports
  • Compress large zone files
  • Consider Terraform/AWS CDK for infrastructure-as-code approaches

Use aws route53 change-resource-record-sets with the exported JSON to recreate records in a new hosted zone. Always verify record TTLs and values match your original configuration.


Many AWS users are surprised to discover there's no direct "Export" button for Route 53 hosted zones in the management console. While you could manually record DNS records using dig commands, this approach becomes impractical for zones with numerous records or when you need frequent backups.

The most reliable methods come from AWS's own tools:

# AWS CLI method to list all records
aws route53 list-resource-record-sets \
    --hosted-zone-id /hostedzone/Z1D633PEXAMPLE \
    --output json > route53_backup.json

For programmatic access in different languages:

// Python using boto3
import boto3
import json

client = boto3.client('route53')
response = client.list_resource_record_sets(
    HostedZoneId='Z1D633PEXAMPLE'
)

with open('route53_export.json', 'w') as f:
    json.dump(response, f, indent=4)

Several open-source tools can simplify the process:

  • Route53-export (Node.js)
  • terraform-aws-route53 (for Terraform users)
  • awscli-zsh-plugin (adds export shortcuts)

When you need to convert between formats:

# Convert JSON to BIND format
jq -r '.ResourceRecordSets[] | 
"\(.Name) \(.TTL) IN \(.Type) \(.ResourceRecords[].Value)"' \
route53_backup.json > zonefile.txt

Create a Lambda function triggered by CloudWatch Events:

// Lambda backup function
exports.handler = async (event) => {
    const AWS = require('aws-sdk');
    const route53 = new AWS.Route53();
    const s3 = new AWS.S3();
    
    const params = { HostedZoneId: 'Z1D633PEXAMPLE' };
    const data = await route53.listResourceRecordSets(params).promise();
    
    await s3.putObject({
        Bucket: 'route53-backups',
        Key: backups/${new Date().toISOString()}.json,
        Body: JSON.stringify(data)
    }).promise();
};