Skip to content

Backup and Bulk Deletion of Route 53 Records

7 minute read
Content level: Intermediate
0

Route 53 requires all DNS records to be deleted before a hosted zone can be removed. For large zones with thousands of records, manual deletion is impractical due to API constraints. This article provides automated AWS CLI bash scripts that handle pagination, batching, and rate limiting to efficiently bulk-delete all records from any hosted zone, regardless of size.

Introduction

Amazon Route 53 is a highly scalable Domain Name System (DNS) web service that enables organizations to route end users to internet applications. While Route 53 excels at managing DNS records at scale, situations arise where you need to decommission hosted zones containing thousands of records.

Route 53 requires all records (except the mandatory NS and SOA records) to be deleted before a hosted zone can be removed. For hosted zones with tens of thousands of records, manual deletion through the AWS Console is impractical. This article provides automated solutions using the AWS CLI to efficiently delete all records from a large hosted zone.

The Challenge

Deleting a hosted zone with a large number of DNS records presents several technical constraints:

  • Route 53 API limits a single ChangeResourceRecordSets request to up to 1,000 changes per batch (a practical limit for reliable batch processing)
  • The ListResourceRecordSets API returns a maximum of 300 resource record sets per page
  • NS (Name Server) and SOA (Start of Authority) records cannot be deleted as they are mandatory for the hosted zone
  • For hosted zones with more than 1,000 records, multiple batched API calls are required

Prerequisites

  • AWS CLI installed and configured with appropriate permissions
  • jq command-line JSON processor installed
  • IAM permissions for route53:ListHostedZones, route53:ListResourceRecordSets, and route53:ChangeResourceRecordSets

Step 1: Back Up Your Records

Before deleting any records, take a backup of the hosted zone. This is critical in case you need to restore records later.

For hosted zones with fewer than 300 records, a single CLI command works:

aws route53 list-resource-record-sets --hosted-zone-id <your-zone-id> > backup.json

For hosted zones with more than 300 records, the API paginates the results. Use the --paginate option with the AWS CLI to automatically handle pagination and retrieve all records:

aws route53 list-resource-record-sets --hosted-zone-id <your-zone-id> --output json --no-paginate > backup.json

Alternatively, you can use the built-in AWS CLI paginator:

aws route53 list-resource-record-sets --hosted-zone-id <your-zone-id> \
  --query "ResourceRecordSets" --output json > backup.json

Verify the backup contains all records:

cat backup.json | jq 'length'

Replace <your-zone-id> with your actual hosted zone ID (e.g., Z1234567890ABC).

Step 2: Choose Your Deletion Approach

Option A: Single-Command Approach (For Zones with Fewer Than 300 Records)

For small hosted zones where all records fit in a single ListResourceRecordSets response (fewer than 300 records), you can delete all records with a single command:

ZONE_ID="<your-zone-id>"

aws route53 change-resource-record-sets --hosted-zone-id "$ZONE_ID" \
  --change-batch "$(aws route53 list-resource-record-sets --hosted-zone-id "$ZONE_ID" | \
  jq -c '{Changes: [.ResourceRecordSets[] | select(.Type != "SOA" and .Type != "NS") | {Action: "DELETE", ResourceRecordSet: .}]}')"

How it works:

  1. Lists all resource record sets in the hosted zone
  2. Filters out NS and SOA records using jq
  3. Creates a DELETE action for each remaining record
  4. Submits all deletions in a single batch

Note: This approach does not handle pagination. If your hosted zone has more than 300 records, use Option B below.

Option B: Batched Deletion Script (For Large Hosted Zones)

For hosted zones with more than 300 records, use the following script that handles pagination and batching automatically(make sure to add "." after your domain name):

#!/bin/bash

# Configuration - replace with your domain name
DOMAIN="example.com."

# Get the hosted zone ID
ZONE_ID=$(aws route53 list-hosted-zones \
  --query "HostedZones[?Name==\`${DOMAIN}\`].Id" \
  --output text | sed 's/\/hostedzone\///')

if [ -z "$ZONE_ID" ]; then
  echo "Error: Hosted zone not found for domain ${DOMAIN}"
  exit 1
fi

echo "Found hosted zone ID: $ZONE_ID"
echo ""
echo "  WARNING: This will delete all records except NS and SOA records."
echo ""
echo "  RECOMMENDATION: Take a backup first using:"
echo "    aws route53 list-resource-record-sets --hosted-zone-id \"$ZONE_ID\" --output json > backup.json"
echo ""
read -p "Have you taken a backup? Do you want to proceed? (yes/no): " confirmation

if [ "$confirmation" != "yes" ]; then
  echo "Deletion cancelled."
  exit 0
fi

echo ""
echo "Starting deletion process..."

batch_count=0

while true; do
  # Fetch records and create delete changes (excluding NS and SOA)
  changes=$(aws route53 list-resource-record-sets \
    --hosted-zone-id "$ZONE_ID" --max-items 1000 | \
    jq -c '{Changes: [.ResourceRecordSets[] | select(.Type != "SOA" and .Type != "NS") | {Action: "DELETE", ResourceRecordSet: .}]}')

  # Check if there are any records left to delete
  record_count=$(echo "$changes" | jq '.Changes | length')

  if [ "$record_count" -eq 0 ]; then
    echo ""
    echo "All records deleted successfully."
    break
  fi

  # Submit the batch deletion
  batch_count=$((batch_count + 1))
  echo "Processing batch $batch_count ($record_count records)..."

  aws route53 change-resource-record-sets \
    --hosted-zone-id "$ZONE_ID" --change-batch "$changes"

  if [ $? -ne 0 ]; then
    echo "Error processing batch $batch_count. Exiting."
    exit 1
  fi

  echo "Batch $batch_count completed."

  # Wait between batches to avoid rate limiting
  sleep 5
done

echo ""
echo "Hosted zone $ZONE_ID is now ready for deletion."
echo "To delete the hosted zone, run:"
echo "  aws route53 delete-hosted-zone --id $ZONE_ID"

How to Use the Script

  1. Create the script file:
nano delete-route53-records.sh
  1. Paste the script content and save (Ctrl+X, then Y, then Enter in nano)

  2. Make it executable:

chmod +x delete-route53-records.sh
  1. Update the DOMAIN variable in the script to match your hosted zone name (include the trailing dot)

  2. Run it:

./delete-route53-records.sh

How the Script Works

  1. Finds the hosted zone ID for the specified domain
  2. Displays a safety warning and waits for confirmation before proceeding
  3. Loops through all records in batches of up to 1,000 at a time
  4. Filters out NS and SOA records (which are required and cannot be deleted)
  5. Submits each batch as a ChangeResourceRecordSets DELETE request
  6. Waits 5 seconds between batches to avoid API rate limiting
  7. Continues until no deletable records remain
  8. Outputs the command to delete the hosted zone once all records are removed

Technical Considerations

  • API Pagination: The --max-items 1000 parameter is a client-side pagination control. The underlying API returns a maximum of 300 records per page, but the AWS CLI handles the pagination internally and returns up to the specified max-items count.
  • Rate Limiting: Route 53 has a default limit of 5 ChangeResourceRecordSets requests per second per account. The 5-second sleep between batches keeps the script well within this limit.
  • Record Filtering: The jq filter select(.Type != "SOA" and .Type != "NS") preserves the mandatory NS and SOA records. Note that this also preserves NS records for delegated subdomains — if you need to delete those, adjust the filter to only preserve NS records matching the zone apex.
  • Idempotency: The script can be safely re-run if interrupted. It will pick up where it left off since already-deleted records will no longer appear in the list.
  • Alias Records: Alias records are included in the deletion. No special handling is needed as they are deleted the same way as standard records.

Step 3: Delete the Hosted Zone

After all records have been deleted (only NS and SOA remain), you can delete the hosted zone:

aws route53 delete-hosted-zone --id <your-zone-id>

Summary

By understanding Route 53's API limitations and implementing a batched deletion strategy, you can efficiently clean up hosted zones containing any number of records. The key points are:

  • Always back up your records before deletion
  • Use batched API calls to stay within safe limits (up to 1,000 changes per request)
  • Filter out NS and SOA records which cannot be deleted
  • Include delays between batches to respect API rate limits
  • The script is idempotent and can be re-run safely if interrupted

Related Resources

AWS
EXPERT
published a month ago208 views