Relational Database Service (RDS) is a feature provided by Amazon AWS so that you can have a MySQL DB (along with other database types) offered as a service. Using RDS, you no longer need to care about database installation, backup, or maintenance. However, you still need to manage the database instance type and class.

Now, what if you want to make a few modifications to your database instance? You can do that from the AWS management console or from the command line with a few clicks/commands. The problem, however, is that the service must be down through this maintenance period.

AWS offers the Muti-AZ feature, which spins up another instance of your database, in a different availability zone, that has the same data as the first one. Hosting your RDS with mutli-AZ turned on will ensure that you never have a downtime when you make a modification or an upgrade/downgrade to your instance. The other instance will continue serving your application/clients till the first one is done modification, after which the new one will have its turn.

The problem with the above approach is that you will pay double the price of a single instance. For some users, availability means everything for them. For example, if a web application hosted on AWS and uses RDS for a backend database serves real-time information about the stock market, then a downtime of as much as a few seconds can cost the company a lot of money. At worst, it may cost them their entire business. But for some other users, they are not willing to pay for an extra instance, but still, they don't want to have downtime when modifying their instance. If you're one of those, read along.

You can enable Mutli-AZ feature on your RDS instance, make the necessary modifications, and then disable the feature. This will ensure that you have zero downtime during the maintenance period and still, you won't pay except for the few minutes during which the extra instance will be taking over.

The following script uses Python 2 and Boto3 to enable multi-az on an RDS instance, upgrade it, then disable multi-az. Effectively, achieving maximum availablity during the upgrade process.

import boto3
import time
import logging

DB = "mytestdb"
client = boto3.client('rds')

def get_db_status():
    response = client.describe_db_instances(DBInstanceIdentifier=DB)
    return response['DBInstances'][0]['DBInstanceStatus']

def downgrade():
    client.modify_db_instance(
        DBInstanceIdentifier = DB,
        DBInstanceClass = "db.t2.micro",
        ApplyImmediately = True
    )
def enable_multiAZ():
    client.modify_db_instance(
        DBInstanceIdentifier = DB,
        MultiAZ=True,
        ApplyImmediately = True
    )

def disable_multiAZ():
    client.modify_db_instance(
        DBInstanceIdentifier = DB,
        MultiAZ=False,
        ApplyImmediately = True
    )

def upgrade():
    client.modify_db_instance(
        DBInstanceIdentifier = DB,
        DBInstanceClass = "db.t2.small",
        ApplyImmediately = True
    )
def wait():
    # Give AWS some time to process the request
    time.sleep(60)
    while get_db_status() == "modifying":
        print ("Waiting for DB to become available")
        time.sleep(60)

enable_multiAZ()
wait()
downgrade()
wait()
disable_multiAZ()

The above code is fairly simple to understand. First, we define the database ID that Boto3 will be using in all the calls that it'd make to AWS. The database ID is the name that you chose for your instance when you created it.

Then, we define the client object that will be used to make the API calls to AWS.

Following, we define an important function, get_db_status. This function will query the database instance for the current status. We need to wait for the last modification to be applied before starting a new one. Otherwise, an exception will be thrown and the script will exit.

The next set of functions will enable/disable Multi-AZ and upgrade/downgrade the instance. You can add whatever modifications you need and not necessarily changing the DB class.

Finally, we execute the functions in turn: enable multi-az, wait for the instance to become available, modify it, wait for the modification to be done, then disable multi-az again.

The interesting thing here is that, throughout the whole operation, you won't lose the instance availability. Not even for a second.