---
title: 'How to Schedule RDS Instances Automatically'
description: 'RDS instances cost the same whether you use them or not. Learn three ways to stop and start them on a schedule, plus the gotchas no one warns you about.'
date: '2026-05-12'
readingTime: '6 min read'
---

## RDS Is Expensive Even When Nobody Is Using It

EC2 hogs the cost-optimization conversation, but in my experience RDS is usually the fatter line item. One idle `db.m5.large` Multi-AZ database in `eu-west-1` costs roughly $240 per month. It does not matter that nobody queried it once all weekend. Now picture the usual sprawl of dev, staging, and QA databases, and you are looking at $1,500 to $3,000 a month for instances that sit dark outside business hours.

RDS is not EC2. It has a few traps that bite the first time, and one of them keeps billing you while you think the database is off. Here is what actually works, where it goes wrong, and the three ways teams get it done.

## The 7-Day Auto-Start Gotcha

Read this before you write a line of code. **AWS automatically restarts any stopped RDS instance after 7 days.** There is no setting. You cannot disable it. AWS does it so security patches land, and that reasoning is fine, but it wrecks the obvious schedule.

Stop on Friday, start on Monday, and you never notice. The problem is the long stops. Park a database for a vacation or a frozen project and on day seven it quietly comes back, then meters away until someone happens to glance at the bill.

So a real scheduler has to do one of two things. Either it stops the instance again the moment AWS wakes it up, or it snapshots and deletes the instance outright and recreates it on demand, which is cheaper but a lot more disruptive. The throwaway Lambda you sketched on a napkin does neither, and that is exactly how the auto-start gets you.

## What You Can Schedule (and What You Cannot)

The boring cases work fine. Standard RDS engines (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server) all stop and start cleanly, on Single-AZ and Multi-AZ alike. Read replicas work too, with the obvious catch that stopping a primary takes its replicas down with it.

Where it falls over:

- Aurora clusters. Different stop API, and they carry their own 7-day limit.
- RDS instances inside an Outposts deployment.
- Instances with active read replicas. Stop the replicas first or the call fails.

Aurora is close enough to feel the same but reaches for `StopDBCluster` instead of `StopDBInstance`. Most third-party tools cover both. Confirm it before you assume it.

## Option 1: AWS Instance Scheduler

AWS ships an official answer here, Instance Scheduler, and it handles both EC2 and RDS. You deploy it through CloudFormation, define schedules as DynamoDB items, and tag each RDS instance with the schedule name you want it to follow.

The good part is the price and the provenance. It is effectively free beyond the Lambda and DynamoDB it runs on, usually under $5/month, it is maintained by AWS, and it deals with the 7-day auto-start by re-stopping instances on the next scheduled run.

The pain shows up at scale. CloudFormation is per account and per region, so the moment you have more than a couple of accounts you are writing automation to manage the automation. Schedules live as raw DynamoDB items, which is a miserable way to change "8 to 7" to "9 to 6". There is no dashboard telling you what is scheduled or what you have saved. And Aurora support reads like an afterthought next to the EC2 path.

It is a good fit when you have one or two accounts, a DevOps engineer who already lives in CloudFormation, and no objection to editing DynamoDB by hand.

## Option 2: Lambda + EventBridge (DIY)

Roll your own: a Lambda that calls `StopDBInstance` and `StartDBInstance`, EventBridge cron rules to fire it, and the instance list parked somewhere (tags, Parameter Store, or hard-coded if you are honest about the prototype).

The demo works in an afternoon. Then production reality arrives:

- The 7-day auto-start still needs handling. Nothing about a custom Lambda exempts you.
- `StopDBInstance` fails outright if the instance has read replicas, so you stop those first, in the right order.
- `StartDBInstance` fails on anything that is not "stopped", so you need backoff and retry around it.
- Multi-AZ failovers can wedge an instance in "modifying" for more than 10 minutes.
- IAM has to be scoped tight or you have handed out far more than you meant to.
- Cross-account scheduling means assuming roles, which means yet more IAM.
- And you need logging and alerting, because a stop that fails silently is the whole problem you were trying to solve.

Budget two to four weeks to get from the afternoon prototype to something that survives the list above. Then keep maintaining it every time AWS changes a state name or an error code.

## Option 3: A Managed Scheduling Service

[ParkMyAWS](https://parkmyaws.com) and tools like it run RDS scheduling for you. Connect an account through an IAM role, pick the RDS instances or Aurora clusters you want parked, set the hours, done.

The 7-day auto-start is handled for you. So is read replica ordering. A failed stop arrives as a notification rather than a line in a CloudWatch log nobody opens until the invoice does the talking.

The cost is real and worth naming. You pay monthly, and you hand a third party an IAM role into your account. For most teams the fee is a rounding error against the savings, since one parked `db.m5.large` covers the bill several times over. For teams where third-party IAM trust is off the table, this is simply not the option, and that is a reasonable line to draw.

## A Realistic Schedule for RDS

Teams overthink this. The defaults that hold up:

- **Dev and QA databases:** weekdays 8 AM to 7 PM in your team's timezone, off overnight and off all weekend.
- **Staging:** same as dev. The exception is scheduled jobs running against it, in which case move those jobs into business hours rather than keeping the database up around the clock.
- **Demo and sandbox:** off by default, started on demand.

Production stays on. Always.

One thing to design around: most RDS instances take 3 to 5 minutes to come back when they start cold. Set the start 10 minutes ahead of when your team actually needs the database, not the minute they sit down.

## Where to Start

Open Cost Explorer, filter to RDS, group by tag or instance ID, and sort by cost. Your top few non-production databases are where the money is hiding. Park those first, then leave it alone and watch the bill for a month before you expand.

The first instance you schedule already pays for whatever tool you used to schedule it. After that it is just savings.
