Skip to main content

Migrate Off Instance Scheduler on AWS Without Double Stops

Inventory what the solution is doing, run one scheduler at a time, and tear the stacks down in the right order.

Instance Scheduler on AWS is a CloudFormation-deployed solution that starts and stops EC2 and RDS resources according to a tag. Moving to another scheduler is mostly an inventory exercise, plus one rule: never let two schedulers own the same resource at once, because the solution’s enforced setting will fight any other tool.

1. Find every tagged resource

The solution reads a tag key that defaults to Schedule; the tag value is the name of a schedule. The key is case sensitive and can be changed at deploy time, so check the hub stack’s Schedule tag key parameter in the CloudFormation console before searching.

Terminal window
aws resourcegroupstaggingapi get-resources \
--tag-filters Key=Schedule \
--resource-type-filters ec2:instance rds:db rds:cluster \
--query "ResourceTagMappingList[].{arn:ResourceARN,tags:Tags}" \
--output json > instance-scheduler-inventory.json

Run it in every account and Region the hub stack or its remote stacks cover.

2. Export the schedules and periods

Install the Scheduler CLI that ships with the solution (it needs Python 3.8 or later and boto3), then dump the configuration. --stack is required on every command.

Terminal window
scheduler-cli describe-schedules --stack instance-scheduler-hub > schedules.json
scheduler-cli describe-periods --stack instance-scheduler-hub > periods.json

A schedule is a group of one or more periods; each period is a running window with a start and stop time. When a schedule has several periods, the solution starts the instance if at least one period is active.

3. Map the fields that change behaviour

Most of the work is in the schedule flags, not the times:

Instance Scheduler fieldWhat it doesWhat to set in the new scheduler
time zonePer schedule; falls back to the stack’s default, which is UTCThe same IANA zone, explicitly
stop_new_instancesDefault true: stops a running instance the first time it is tagged outside a periodDecide whether first attachment should stop immediately
enforcedStops an instance started manually outside a period, and restarts one stopped manually inside a periodReplace with a documented override process
retain_runningLeaves an instance running at period end if it was started manually before the period beganUsually an override with an expiry
hibernateHibernates EC2 instead of stopping, if the AMI supports itCheck the new tool’s stop verb
ssm-maintenance-windowAdds an SSM maintenance window as a running periodAdd the window as an extra start and stop, or the instance will be off during it

4. Suspend, then cut over

Do not delete anything yet. In the CloudFormation console, update the hub stack and set Enable scheduling to No. That suspends all scheduling operations while leaving tags, tables and schedules intact, so you can roll back by setting it to Yes.

Then enable the replacement schedules. For the first week, compare the replacement’s actions with CloudTrail:

Terminal window
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=StopInstances \
--start-time 2026-09-24T00:00:00Z

The Username and user identity on each event show which principal made the call: every stop should come from the new scheduler, none from the solution.

5. Remove the tags and the stacks

Once a full week has run cleanly, remove the tag so nothing re-enrols by accident:

Terminal window
aws resourcegroupstaggingapi untag-resources \
--resource-arn-list arn:aws:ec2:eu-west-1:123456789012:instance/i-0abc1234def567890 \
--tag-keys Schedule

AWS’s uninstall guidance is to delete all custom schedule stacks before the solution itself, and to delete the hub stack together with every remote stack in secondary accounts.

Terminal window
aws cloudformation delete-stack --stack-name instance-scheduler-hub

If DynamoDB table protection (the Retain data and logs parameter at deploy time) is enabled on the hub stack, CloudFormation keeps the solution’s DynamoDB tables and KMS key. Disable it before deleting the stack, or delete those resources by hand afterwards.

Rebuilding the schedules in ZopNight

Each Instance Scheduler schedule becomes a ZopNight schedule with a name, a description, an IANA timezone and cron start and stop expressions; a schedule can hold several crons, which covers multi-period schedules. Resources attach individually or through a resource group, where members can be ordered with a per-resource delay. Overrides force a resource on or off until an expiry, which replaces most uses of enforced and retain_running, and each start, stop or failure can notify Slack, Teams, Google Chat or a webhook. EC2 and RDS are both on the start and stop list; the EC2 scheduling page and the cron scheduling guide help with the translation.

Stop watching the waste.
Start cutting it.

See. Find. Fix. Automatic.

Connect your first cloud account in under 5 minutes. See your first remediation in under 7. No credit card required.

CDCR connect detect classify remediate
full audit every action traceable
read-only default access
Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console· Multi-cloud automation· Production-ready in 30 min· SOC 2 · ISO 27001· 20–60% off the bill, first month· 4 platforms · 1 console·