How we reduced non-production AWS compute costs by 60%+ using EventBridge Scheduler, without Lambda or SSM Automation
Non-production infrastructure is one of the easiest places to reduce cloud costs.
Production servers generally need to run 24/7. Development, staging, QA, and testing environments usually don’t. Yet it is common to find non-production EC2 instances running continuously, even when nobody is using them overnight or on weekends.
On a recent client project, I implemented a simple AWS cost-optimization solution that automatically stops and starts non-production EC2 instances according to the team’s working schedule.
The interesting part was that we didn’t use Lambda, SSM Automation, or any custom code.
Instead, I used Amazon EventBridge Scheduler’s Universal Target to call the Amazon EC2 API directly.
The result was a lightweight solution with minimal maintenance and significant compute-cost savings.
The Challenge: Non-Production Servers Running 24/7
During the client infrastructure review, we identified several EC2 instances used for development and staging that remained powered on outside working hours.
For example, a typical development server might only be actively used between 8 AM and 8 PM on weekdays.
Running it continuously means paying for approximately:
- 24 hours × 7 days
- Around 730 hours per month
But if the server only needs to run during working hours, the actual compute usage can be dramatically lower.
This created an opportunity to reduce AWS costs without changing the infrastructure architecture or affecting production workloads.
The Cost Optimization Opportunity
Here’s a simplified comparison:
| Schedule | Approx. Hours Running / Month | Approx. Compute Saving |
| 24/7 | ~730 hours | 0% |
| Weekdays, 8 AM–8 PM | ~260 hours | ~64% |
| Weekdays, 10 AM–7 PM | ~195 hours | ~73% |
The exact savings depend on the EC2 instance type, region, working schedule, and other infrastructure costs.
Stopping an EC2 instance stops the associated compute charges, although attached EBS volumes continue to incur storage charges.
For environments with several development and staging servers, the savings can become substantial.
Why We Chose EventBridge Scheduler
A common approach is to create a Lambda function that runs on a schedule and calls the EC2 API.
Another option is to use EventBridge to trigger an SSM Automation runbook.
Both approaches work, but for this particular use case, neither was necessary.
Amazon EventBridge Scheduler can invoke AWS APIs directly through its Universal Target capability.
That means the architecture can be reduced to:
EventBridge Scheduler → EC2 API
Instead of:
EventBridge → Lambda → EC2 API
or:
EventBridge → SSM Automation → EC2
This provided several advantages:
- No Lambda function to deploy.
- No Lambda runtime to maintain.
- No application code.
- No SSM Automation document.
- Fewer moving parts.
- Simple IAM permissions.
- Easy troubleshooting.
- Very low ongoing maintenance.
Step 1: Tag the Non-Production EC2 Instances
Before creating the schedules, I tagged the EC2 instances that were allowed to be managed by the automation.
For example:
Key: Environment
Value: non-prod
This provided an additional security boundary around the automation.
The schedule itself contains the specific EC2 instance IDs, while the IAM permissions are restricted using the resource tag.
This means the automation role is not intended to be a general-purpose EC2 administration role.
For each instance, I also recorded its EC2 Instance ID because those IDs are required when configuring the EventBridge Scheduler target.
Step 2: Create a Dedicated IAM Role
EventBridge Scheduler needs an IAM role that it can assume when executing the scheduled API call.
The trust relationship allows only the Scheduler service to assume the role:
{
“Version”: “2012-10-17”,
“Statement”: [
{
“Effect”: “Allow”,
“Principal”: {
“Service”: “scheduler.amazonaws.com”
},
“Action”: “sts:AssumeRole”
}
]
}
I then created a permissions policy allowing the role to perform the required EC2 actions.
The important principle here is least privilege.
The automation doesn’t need administrative access to EC2. It only needs the permissions required to start and stop the intended instances.
Example:
{
“Version”: “2012-10-17”,
“Statement”: [
{
“Effect”: “Allow”,
“Action”: [
“ec2:StartInstances”,
“ec2:StopInstances”,
“ec2:DescribeInstances”
],
“Resource”: “*”,
“Condition”: {
“StringEquals”: {
“ec2:ResourceTag/Environment”: “non-prod”
}
}
}
]
}
The ec2:ResourceTag/Environment condition provides an additional layer of protection by limiting the actions to instances carrying the expected Environment=non-prod tag.
Step 3: Create the Stop Schedule
The first EventBridge Scheduler schedule shuts down the non-production instances at the end of the working day.
For the client’s working schedule, I configured the schedule for 8 PM on weekdays.
The important configuration was:
Schedule name: non-prod-stop-weekdays
Schedule type: Recurring schedule
Schedule: Weekdays at 8:00 PM
Time zone: Asia/Kolkata
Target: EventBridge Scheduler Universal Target
AWS service: EC2
API: StopInstances
The input passed to the EC2 API contains the instance IDs:
{
“InstanceIds”: [
“i-0abc123”,
“i-0def456”
]
}
One important detail is the time zone.
If the schedule is intended to run according to local business hours, the time zone should be configured explicitly rather than relying on UTC conversion.
For teams operating in India, for example, using Asia/Kolkata makes the schedule much easier to understand and maintain.
Step 4: Create the Start Schedule
The second schedule performs the opposite operation.
It starts at the beginning of the working day.
Example configuration:
Schedule name: non-prod-start-weekdays
Schedule: Weekdays at 8:00 AM
Time zone: Asia/Kolkata
Target: EventBridge Scheduler Universal Target
AWS service: EC2
API: StartInstances
Input:
{
“InstanceIds”: [
“i-0abc123”,
“i-0def456”
]
}
The same IAM execution role can be used for both schedules.
At this point, the complete automation consists of:
1 IAM role + 2 EventBridge schedules
There is no Lambda function and no SSM Automation workflow involved.
Managing Multiple EC2 Instances
The EC2 StartInstances and StopInstances APIs accept multiple instance IDs.
That means one schedule can manage several non-production servers.
For example:
{
“InstanceIds”: [
“i-0abc123”,
“i-0def456”,
“i-0ghi789”
]
}
This works well when the number of development and staging servers is relatively small.
There is one trade-off.
When a new non-production server is introduced, its Instance ID needs to be added to the schedule’s input.
For a small environment, this is a reasonable trade-off for eliminating an entire automation layer.
Why This Approach Works Well for Small Dev/Staging Environments
I wouldn’t recommend forcing the same architecture onto every AWS environment.
For a large and highly dynamic infrastructure fleet, a Lambda-based or Infrastructure-as-Code-driven approach may provide better automation and fleet discovery.
But for a handful of relatively stable development and staging instances, EventBridge Scheduler is extremely practical.
The architecture is simple:
┌─────────────────────┐
│ EventBridge │
│ Scheduler │
└──────────┬──────────┘
│
EC2 API Call
│
┌────────────▼────────────┐
│ Amazon EC2 │
│ StartInstances / │
│ StopInstances │
└─────────────────────────┘
There is no application code sitting between the scheduler and EC2.
Important Considerations
This solution is focused specifically on EC2 compute costs. There are several things that need to be considered before implementing it.
EBS Storage Costs Continue
Stopping an EC2 instance does not eliminate the cost of its attached EBS volumes.
EBS storage continues to incur charges even while the instance is stopped.
So the solution primarily targets EC2 compute costs, not the entire infrastructure bill.
Elastic IP Considerations
Elastic IP behavior should also be reviewed when implementing scheduled shutdowns.
An Elastic IP that remains associated with a stopped instance can incur charges, so unused public IP resources should be monitored as part of the overall cost-optimization exercise.
Running Jobs Will Be Interrupted
Stopping an instance is not the same as gracefully pausing an application.
Any process running on the server when the stop schedule executes can be interrupted.
This is particularly important for:
- CI/CD jobs
- Automated testing
- Long-running builds
- Data processing
- Development databases
- Temporary environments
- Background workers
The schedule should therefore be aligned with the team’s actual working pattern.
What About RDS?
The same concept can be applied to other AWS resources, but the implementation is different.
For example, development and staging databases hosted on Amazon RDS may also contribute significantly to non-production costs.
RDS has its own operational considerations and stop/start capabilities, so database scheduling should be designed separately rather than assuming the EC2 schedule will handle it.
Security Best Practice: Separate Non-Production Automation
One of the most important aspects of this implementation wasn’t the schedule itself.
It was the permission boundary.
Automation should never have more access than it requires.
By combining:
- A dedicated IAM role
- A restricted trust relationship
- Specific EC2 actions
- Environment=non-prod tagging
- Explicit instance IDs
we created a much safer automation model than giving a scheduling role broad EC2 permissions.
This is especially important in environments where production and non-production workloads exist in the same AWS account.
The Result
On the client project, this approach gave us a simple way to reduce unnecessary EC2 runtime without introducing another piece of infrastructure.
The implementation required:
- One IAM role
- Two EventBridge Scheduler schedules
- EC2 environment tags
- A list of non-production instance IDs
No Lambda function.
No SSM Automation document.
No custom script.
No server-side cron job.
For the client’s non-production workloads, running servers only during business hours reduced unnecessary compute runtime significantly, with potential savings of 60%+ compared with running the same instances 24/7, depending on the exact schedule.
More importantly, the solution requires very little ongoing maintenance.
When Should You Use This Approach?
I recommend considering EventBridge Scheduler directly against EC2 when:
- You have a small or medium number of development/staging instances.
- Instance IDs don’t change frequently.
- Your working schedule is predictable.
- You want a serverless solution.
- You don’t need complex instance discovery logic.
- You want to avoid maintaining Lambda code.
- You want a simple, auditable architecture.
For large dynamic fleets, you may want a more automated approach that discovers resources through tags or integrates with Infrastructure as Code.
But if your requirement is simply:
“Start these development servers every weekday morning and stop them every evening.”
you may not need Lambda at all.
Final Takeaway
Cloud cost optimization doesn’t always require a complicated FinOps platform or a large automation framework.
Sometimes the biggest savings come from identifying infrastructure that simply doesn’t need to run continuously.
In this client project, I used Amazon EventBridge Scheduler’s Universal Target to call the EC2 API directly and automate the shutdown and startup of non-production servers.
The result was a straightforward architecture with fewer components, minimal maintenance, and significant potential compute savings.
If your AWS development, QA, or staging environments are running 24/7, reviewing their operating schedules should be one of the first steps in your cloud cost-optimization process.
At Geeks Solutions, we help businesses optimize AWS and Azure infrastructure, automate cloud operations, improve security, and reduce unnecessary cloud spending through practical DevOps and cloud engineering solutions.
Frequently Asked Questions
You can automatically shut down AWS development servers after business hours by using Amazon EventBridge Scheduler to call the EC2 StopInstances API directly. This approach can automate AWS dev server auto shutdown without requiring a Lambda function or SSM Automation.
Yes. EventBridge Scheduler can start and stop EC2 instances without Lambda by using its Universal Target feature to call AWS EC2 APIs such as StartInstances and StopInstances. This provides a simpler serverless solution for scheduled EC2 management.
Automatically shutting down AWS development and staging servers outside working hours can reduce EC2 compute runtime by 60% or more compared with running instances 24/7. The actual AWS cost savings depend on the instance type, region, and shutdown schedule. EBS storage charges continue while an instance is stopped.
Create two Amazon EventBridge Scheduler schedules: one using the EC2 StopInstances API to stop the instances at the end of the working day, and another using StartInstances to start them the next morning. Configure the appropriate time zone, IAM execution role, and EC2 instance IDs.
For a small and relatively stable development or staging environment, EventBridge Scheduler is a simple way to automatically stop non-production EC2 instances. It can call EC2 APIs directly without Lambda or SSM Automation, reducing infrastructure complexity and ongoing maintenance.


