The saving
Weekdays 07:00–19:00 is 60 of 168 hours. Stopping compute outside that window removes around 60% of its cost. EBS volumes, snapshots and storage keep billing.
1. Tags
| Tag | Example |
|---|---|
Environment | dev, test, prod. Automation never touches prod |
Schedule | office-hours-ist |
ScheduleOverrideUntil | 2026-10-31 |
Enforce with tag policies (Organizations) and SCPs/Config rules for required tags.
2. Option A: Instance Scheduler on AWS
AWS's solution (CloudFormation) supports EC2, Auto Scaling groups and RDS/Aurora across accounts and regions, driven by a Schedule tag and schedule definitions (periods, time zones). Good when you have many accounts and want a maintained solution.
3. Option B: EventBridge Scheduler with universal targets
No code needed for simple actions. EventBridge Scheduler can call AWS APIs directly:
aws scheduler create-schedule --name stop-dev-ec2 --schedule-expression "cron(15 19 ? * MON-FRI *)" \
--schedule-expression-timezone "Asia/Kolkata" --flexible-time-window Mode=OFF \
--target '{"Arn":"arn:aws:scheduler:::aws-sdk:ec2:stopInstances",
"RoleArn":"arn:aws:iam::123456789012:role/scheduler-dev-ops",
"Input":"{\"InstanceIds\":[\"i-0abc\",\"i-0def\"]}"}'
For tag-based selection, target an SSM Automation document or a small Lambda that looks up resources by tag and honours the override tag.
4. Per-service actions
| Service | Stop | Start | Notes |
|---|---|---|---|
| EC2 | aws ec2 stop-instances | start-instances | Instance store data is lost; public IPs change without Elastic IP |
| Auto Scaling group | update-auto-scaling-group --min-size 0 --max-size 0 --desired-capacity 0 | Restore saved values | Or scheduled actions on the ASG itself |
| RDS instance | aws rds stop-db-instance | start-db-instance | Auto-starts after 7 days; re-stop it on schedule |
| Aurora cluster | aws rds stop-db-cluster | start-db-cluster | Same 7-day rule; or Serverless v2 with min 0 ACU |
| EKS managed node group | aws eks update-nodegroup-config --scaling-config minSize=0,maxSize=3,desiredSize=0 | Restore | Control plane still billed; Karpenter: set NodePool limits / scale workloads to 0 |
| ECS service | aws ecs update-service --desired-count 0 | Restore count | Fargate billing stops with tasks |
| Redshift provisioned | aws redshift pause-cluster | resume-cluster | Or Redshift Serverless |
| SageMaker notebooks | Lifecycle config auto-stop on idle | n/a | Common hidden cost |
5. Overrides and notifications
- A Slack/Teams message 30 minutes before stop listing resources and how to set the override tag.
- Override tag with a maximum length (e.g. 14 days), enforced by the automation.
- Never stop during a running pipeline deployment if environments are deployed by CI.
6. Watch side effects
- Cron jobs, backups and agents on dev instances: reschedule into working hours.
- Shared dev services (databases used by many teams) may need longer windows.
- Licences tied to hosts; Windows instances with activation requirements.
7. Report savings
Monthly: hours stopped × on-demand rate per resource, or the dev/test accounts' EC2/RDS cost month on month in Cost Explorer.
Tip
Start with one dev account for two weeks, then roll out by account. Teams accept schedules quickly once they see the override works and their numbers drop.
Checklist
- Environment and schedule tags enforced
- Instance Scheduler or EventBridge Scheduler chosen
- EC2, ASG, RDS/Aurora, EKS, ECS, Redshift covered
- RDS 7-day auto-start handled
- Override tag and pre-stop notification
- Side effects checked; savings reported