---
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 — and 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 gets all the attention when teams talk about cost optimization, but RDS is often the bigger line item. A single `db.m5.large` Multi-AZ database in `eu-west-1` runs about **$240 per month** sitting idle. Scale that to a handful of dev, staging, and QA databases and you are easily burning **$1,500 to $3,000 a month** on instances nobody touches outside business hours.

Unlike EC2, RDS has some quirks that catch teams off-guard the first time they try to schedule it. This post walks through what actually works, what to watch out for, and three ways to get it done.

## The 7-Day Auto-Start Gotcha

Before you do anything, you need to know this: **AWS automatically restarts any stopped RDS instance after 7 days**. It is not optional. It is not configurable. It is built into the service to ensure security patches get applied.

This means a naive "stop on Friday, start on Monday" schedule works fine for weekends, but a database stopped for vacation, a long weekend, or a frozen project will silently restart and burn money until someone notices.

Any scheduling solution worth using either:

- Stops the instance again right after AWS restarts it
- Or uses snapshots to fully delete and recreate the instance (cheaper, more disruptive)

The simple Lambda you sketched on a napkin probably does neither.

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

RDS scheduling works for:

- Standard RDS instances (MySQL, PostgreSQL, MariaDB, Oracle, SQL Server)
- Single-AZ and Multi-AZ deployments
- Read replicas (with caveats — stopping a primary stops the replicas)

It does **not** work for:

- Aurora clusters — these use a different stop API and have their own 7-day limit
- RDS instances inside an Outposts deployment
- Instances with active read replicas (you must stop replicas first)

If you are running Aurora, the approach is similar but uses `StopDBCluster` instead of `StopDBInstance`. Most third-party tools support both, but check before assuming.

## Option 1: AWS Instance Scheduler

AWS publishes an official solution called Instance Scheduler that supports both EC2 and RDS. You deploy it via CloudFormation, define schedules in DynamoDB, and tag your RDS instances with the schedule name.

**What works well:**

- Free aside from the underlying Lambda and DynamoDB costs (typically under $5/month)
- Officially maintained by AWS
- Handles the 7-day auto-start by re-stopping instances on the next scheduled run

**What is painful:**

- CloudFormation deployment per account and per region — multi-account setups need automation on top
- Schedules live in DynamoDB items, which is not a friendly editing experience
- No central dashboard showing what is scheduled or how much you have saved
- Aurora support is bolted on and less polished than EC2

Good fit if you have one or two accounts, a DevOps engineer who is comfortable with CloudFormation, and you are happy editing DynamoDB to change a schedule.

## Option 2: Lambda + EventBridge (DIY)

The build-your-own approach: write a Lambda that calls `StopDBInstance` and `StartDBInstance`, trigger it with EventBridge cron rules, store the list of instances somewhere (tags, Parameter Store, or hard-coded).

This sounds simple until you hit reality:

- The 7-day auto-start needs handling
- `StopDBInstance` fails if the instance has read replicas — you need to stop those first, in order
- `StartDBInstance` fails if the instance is in any state other than "stopped" — you need backoff and retry
- Multi-AZ failovers can leave an instance in "modifying" state for 10+ minutes
- IAM permissions need to be scoped carefully or you risk granting too much
- Cross-account scheduling means assuming roles, which means more IAM
- You need logging, alerting, and a way to know when a stop failed silently

A working prototype takes an afternoon. A production-grade version that handles all of the above takes two to four weeks and then needs ongoing maintenance every time AWS changes something.

## Option 3: A Managed Scheduling Service

Tools like [ParkMyAWS](https://parkmyaws.com) handle RDS scheduling as a managed service. You connect an AWS account via IAM role, pick which RDS instances (or Aurora clusters) you want scheduled, set the hours, and it runs.

The 7-day auto-start is handled automatically. Read replica ordering is handled automatically. Failed stops surface as notifications instead of silent errors in a CloudWatch log nobody reads.

Tradeoff: monthly subscription, and you grant a third party an IAM role. For most teams the subscription is a small fraction of the savings — a single scheduled `db.m5.large` pays for the service many times over. For some teams the IAM trust requirement is a non-starter, which is fair.

## A Realistic Schedule for RDS

Most teams overcomplicate this. Start here:

- **Dev and QA databases:** Weekdays 8 AM to 7 PM in your team's timezone. Stop overnight, stop on weekends.
- **Staging:** Same as dev unless you run scheduled jobs against it. If you do, run those jobs during business hours instead.
- **Demo and sandbox:** Stop by default. Start on demand when needed.

Production stays on. Always.

Expect cold-start times of **3 to 5 minutes** for most RDS instances when they come back up. Schedule the start 10 minutes before your team needs the database, not at the moment they need it.

## Where to Start

Pull up Cost Explorer, filter by service to RDS, and group by tag or instance ID. Sort by cost. Your top three or four non-production databases are where the money is.

Schedule those first. Watch the bill for a month. Then expand from there.

The first RDS instance you schedule pays for whatever tool you use to schedule it. Everything after that is pure savings.
