AWS RDS Database Running Scheduler
This AWS CDK construct provides an automated solution for managing the operational hours of Amazon RDS DB instances and Aurora clusters. It identifies target resources based on user-defined tags and leverages AWS EventBridge Scheduler to trigger a Lambda function at specified times, ensuring databases only run during active working hours. This significantly reduces costs for non-production environments. The current stable version is 3.1.4, with frequent patch and minor releases. Key differentiators include its tag-based targeting, 'Durable Execution' Lambda that polls for desired resource states, and optional Slack notifications for operational status. It supports cron-based scheduling with configurable timezones, times, and weekdays, enabling precise control over database availability and cost optimization.
Common errors
-
Error: Invariant Violation: The construct ID 'MyRDSScheduler' is already in use by a sibling construct. Choose a unique ID for each construct within the same scope.
cause Attempting to create two constructs with the same ID within the same parent scope.fixEnsure each construct instance (e.g., `new RDSDatabaseRunningScheduler(...)`) has a unique string ID within its parent scope (e.g., `stack`). -
Error: Unable to resolve object: Fn::Join: Invalid type for Fn::Join
cause Common CDK synthesis error indicating an issue with how references or intrinsic functions are used, often due to passing non-string values where strings are expected.fixReview the properties passed to `RDSDatabaseRunningSchedulerProps`, especially for `targetResource` and `secrets`, ensuring all values are correctly typed as strings or construct references. -
TypeError: Cannot read properties of undefined (reading 'account')
cause CDK environment variables (CDK_DEFAULT_ACCOUNT, CDK_DEFAULT_REGION) are not set when synthesizing or deploying, and the stack's `env` property is not explicitly provided or correctly conditionally accessed.fixDefine the `env` property for your `Stack` with explicit `account` and `region` values, or ensure `CDK_DEFAULT_ACCOUNT` and `CDK_DEFAULT_REGION` are set in your environment (e.g., `export CDK_DEFAULT_ACCOUNT="123456789012"`).
Warnings
- breaking This package requires Node.js version 20.0.0 or higher. Older Node.js versions are not supported and will lead to errors during CDK synthesis or deployment.
- gotcha The `targetResource.tagKey` and `targetResource.tagValues` must exactly match the tags applied to your RDS instances or Aurora clusters. Mismatched casing or values will result in resources not being managed by the scheduler.
- gotcha The `slackSecretName` property expects the name of an AWS Secrets Manager secret that contains the Slack webhook URL. If the secret does not exist or the Lambda function lacks permissions to access it, Slack notifications will fail silently or cause Lambda invocation errors.
- gotcha The `timezone` string for `startSchedule` and `stopSchedule` must be a valid IANA timezone identifier (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo'). Invalid timezone strings may lead to incorrect scheduling or deployment failures.
Install
-
npm install aws-rds-database-running-scheduler -
yarn add aws-rds-database-running-scheduler -
pnpm add aws-rds-database-running-scheduler
Imports
- RDSDatabaseRunningScheduler
const { RDSDatabaseRunningScheduler } = require('aws-rds-database-running-scheduler');import { RDSDatabaseRunningScheduler } from 'aws-rds-database-running-scheduler'; - RDSDatabaseRunningScheduleStack
import RDSDatabaseRunningScheduleStack from 'aws-rds-database-running-scheduler';
import { RDSDatabaseRunningScheduleStack } from 'aws-rds-database-running-scheduler'; - App
import { App, Stack } from 'aws-cdk-lib';
Quickstart
import { App, Stack } from 'aws-cdk-lib';
import { RDSDatabaseRunningScheduler } from 'aws-rds-database-running-scheduler';
import { Secret } from 'aws-cdk-lib/aws-secretsmanager';
const app = new App();
const stack = new Stack(app, 'MyRdsSchedulerStack', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT ?? '',
region: process.env.CDK_DEFAULT_REGION ?? ''
}
});
// Create a placeholder secret for Slack webhook (replace with your actual secret management)
const slackWebhookSecret = new Secret(stack, 'SlackWebhookSecret', {
secretName: 'example/slack/webhook',
description: 'Secret for Slack webhook URL (for RDS scheduler notifications)',
secretStringValue: process.env.SLACK_WEBHOOK_URL ?? 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX'
});
new RDSDatabaseRunningScheduler(stack, 'MyRDSScheduler', {
targetResource: { tagKey: 'WorkHoursRunning', tagValues: ['YES'] },
secrets: { slackSecretName: slackWebhookSecret.secretName },
enableScheduling: true,
startSchedule: { timezone: 'Asia/Tokyo', minute: '50', hour: '7', week: 'MON-FRI' },
stopSchedule: { timezone: 'Asia/Tokyo', minute: '5', hour: '19', week: 'MON-FRI' }
});
app.synth();