Automate Updating Thousands of Record Sets in Route53 using Nodejs

In our previous blog (http://blog.powerupcloud.com/2016/09/26/create-hosted-zones-in-route53-and-import-the-record-sets-using-node-js/) , we have automated the multiple hosted zones creation and importing the record sets into them.

In this blog, we are showing how you can automate updating the resource record set which is already available in Route53. We are going to update the A record IP value to ‘A’ Alias value pointing to the ELB Endpoint.

So, we are already having multiple hosted zones available in our account and one zone has more than 100 records. How you will update the A record if more than 100 records are available? Here’s is the solution:

Listing all the Hosted Zones in a file

The snnipet of the script is as follows:

    route53.listHostedZones({}, function(err, data) {
        if (err) console.log(err, err.stack);
        else {
            for (var i in data.HostedZones) {
                var zoneid = []
                zoneid.push(data.HostedZones[i].Id + "\n");
                for (var j in zoneid) {
                    fs.appendFile("zones.txt", zoneid[j], function(err) {
                        if (err) console.log(err)
                        else console.log("zone id appended in file");
                    });
                }
            }
        }
    });

So this script will get the Zone Id of all the hosted zones available and save it in a text file zone.txt. So, after executing this script the zone.txt will have the zone ids in each line as shown below:

/hostedzone/Z1F9TRA0OIUSXK
/hostedzone/Z1QTRDVXPRRM0Q
/hostedzone/Z2DZKSDACI5Q1H
/hostedzone/Z3PPNK2BKN9YSM
...................

Updating the Record Sets

In the first section of the code, we are reading the zone.txt file which contains the Hosted Zone id of all the zones available. We have used “line-reader” module of Nodejs which will read each line of the text file one by one and loop through all the zones with storing each line in a variable called “HostedZoneId”.

    lineReader.eachLine('zones.txt', function(line, last) {
        console.log(line);
        var recordparams = {
            HostedZoneId: line,
        }

Next, for each of the hosted zone available, we have used listResourceRecordSets() API to list all the record sets available for that hosted zone.

    route53.listResourceRecordSets(recordparams, function(err, data) {
            if (err) console.log(err, err.stack);
            else {

Next, we have applied a for loop on all the record sets. So, it will loop through all the record sets available and check for a specific IP. If the IP matches, it will get the record set name with the matching IP and store it in a variable called “name”.

    for (var j in data.ResourceRecordSets) {
      if (data.ResourceRecordSets[j].Type == 'A') {
        for (var k in data.ResourceRecordSets[j].ResourceRecords) {
           if (data.ResourceRecordSets[j].ResourceRecords[k].Value == 'xx.xx.xxx.xx') {
              name = data.ResourceRecordSets[j].Name;

Once we get the record name for which we need to do the required change, we are passing this name to the params used by the changeResourceRecordSets() API.

var delparams = {  
  ChangeBatch: {
    Changes: [{
      Action: 'UPSERT',
      ResourceRecordSet: {
         Name: name,
         Type: 'A',
         AliasTarget: {                                                            
              DNSName: 'xxxxxxxxxx.ap-south-1.elb.amazonaws.com',                   
              EvaluateTargetHealth: false,                                           
              HostedZoneId: 'ZP97RAFLXTNZK'                                          
              },                                                                     
         }                                                                    
      }],                                                                           
      Comment: 'Updating A Record'                                                  
    },                                                                               
   HostedZoneId: line                                                                 };
route53.changeResourceRecordSets(delparams, function(err, data) {  
 if (err) console.log(err, err.stack);
 else {
    sleep.sleep(2);
    console.log(data);
  }
});

So we need to pass the following params for the change:

  • DNS Name in Alias Target: The ELB Endpoint to be passed as the A Alias Record Value.
  • HostedZoneId in Alias Target: This is the ZoneId of the ELB. (You can get the HostedZoneId of the ELB in the EC2 Console)
  • HostedZoneId in ChangeBatch: The hosted zone available in Route53 for which we are going to do that change.

Since, there is some limit on changeResourceRecordSets() API (Five requests per second per AWS account. If you submit more than five requests per second, Amazon Route 53 returns an HTTP 400 error), so we are adding a timeout of 2 seconds. Hence, after updating one record, the script will wait for 2 seconds and then proceed to update the next value.

Updating the next 100 Records

changeResourceRecordSets() will update the first 100 records only. So, for the next 100 records, you need to pass the “NextRecordName” in the “StartRecordName” of the params and apply the same logic again. So, it will start looping through the next 100 records and updates the value. The HostedZoneId in params will be the Hosted Zone Id of the zone which has more than 100 records.

    next = data.NextRecordName;
    var params = {
        HostedZoneId: 'Z469O0K0J9QOS',
        StartRecordName: next,
    };
    route53.listResourceRecordSets(params, function(err, data) {
      if (err) console.log(err, err.stack);
      else {
       for (var j in data.ResourceRecordSets) {
        if (data.ResourceRecordSets[j].Type == 'A') {
          for (var k in data.ResourceRecordSets[j].ResourceRecords) {
            if (data.ResourceRecordSets[j].ResourceRecords[k].Value == 'xx.xx.xxx.xx') {
                name = data.ResourceRecordSets[j].Name; 

Since we have approx 800 records in one hosted zone, so we have applied the same logic 8 times.

The full scripts for listing hosted zone (listhostedzone.js) and updating recordsets (updaterecordset.js) are available here → https://github.com/powerupcloud/Route53-1.git

Hope it will reduce the manual efforts you put in so far. Happy Automation..!! :)

Wish you all a very Happy New Year ..!! :)

Priyanka Sharma

Priyanka is Senior Cloud and DevOps Engineer. She can churn out CloudFormation templates at a moment's notice and play with Chef/Ansible. Dancing, music, badminton and word games are her hobbies

comments powered by Disqus