How to increase RDS storage automatically

As for today, Amazon Aurora is the only RDS database that does not require to provision a fixed storage, it grows storage as needed, from 10GB up to 64TB. If you use the other MySQL-compatible databases, either RDS for MySQL or RDS for MariaDB, you have to provision the storage in advance. So you have to guess a initial number when you create the instance.

A random number?

How do you allocate the most sensible storage? It’s usually a compromise between:

  • costs (you pay for a fix amount for every GB, regardless if you use it or not)
  • IOPS you need (unless you use provisioned IOPS)
  • forecasting future usage
  • potential downtime during scaling up

plus the golden rule that you can always scale up RDS storage (as for any EBS) but you cannot reduce storage size once it has been allocated unless you are keen in creating a new RDS instance and performing a mysqldump.

How long does it take?

Before looking at options on how to automatically increase the size of RDS, first of all let’s remember that the scaling process can take several hours (or days) and even if the RDS instance will be available for use it is likely going to experience performance degradation. The exact time depends on several factors such as database load, storage size, storage type, amount of IOPS provisioned and it’s pretty hard to give a fixed number for that. And let’s add that you have no way to perform any other change to the instance while the process is taking place.  But that is again  one more reason to have it done automatically as you could as well combine it with other metrics and/or avoid peak times during the day.

Make it grow

Even if you choose a sensible size, you still need to be sure that you do not run of storage at some point and you most likely like to have a way to automatically increase the storage on a Multi AZ RDS database once the free storage drops below a certain threshold (let’s say 10% of allocated storage as an example).

How do you trigger it automatically, either to happen immediately or in the next scheduled maintenance windows?

  1. You create a CloudWatch alarm for the RDS (note that the limit is not a percentage of the storage) that sends a notification as well when in error
    aws cloudwatch put-metric-alarm --alarm-name "my-storage-alarm" --metric-name "FreeStorageSpace" --namespace "AWS/RDS" --statistic "Average" --period 300 --evaluation-periods 1 --threshold 1000 --comparison-operator "LessThanOrEqualToThreshold" --dimensions "Name=DBInstanceIdentifier,Value=my-instance" --alarm-actions "my-triggered-action"
  2. You add a Cron job on a EC2 that runs every few minutes relying the AWS Command Line Interface (CLI).
  3. Once the CloudWatch alarm is in ERROR, the bash script triggers a modify instance with the new value (in GB) for the allocated storage
    rds-modify-db-instance "my-instance" --allocated-storage 1200 --apply-immediately
  4. You can finally send an email to the administrator and recreate the CloudWatch alarm (with the new storage limit)

To summarize, you have a mix of bash and CLI and still your EC2.  A very simple improvement is to rely on a AWS Lambda to trigger the scale up, delete the old alarm and create a new one. This removes entirely the need of a EC2, schedule jobs or SPOF and CloudWatch can easily trigger it.