AWS Zero to Hero day 4 - part 4


Automating EC2 Instance Start/Stop with AWS Lambda and EventBridge
Introduction
In a cost-conscious cloud environment, optimizing resource usage is critical. One effective way to manage EC2 instance costs is to automate the process of starting and stopping instances during business hours. In this blog, we’ll walk through a clean and efficient approach using AWS Lambda and EventBridge, with Python (Boto3) to control instances based on tags.
Objective
To automatically start or stop specific EC2 instances during defined hours using a Lambda function. Instances are identified using a custom tag, enabling flexibility and control.
Scenario
You're an AWS expert managing a budget-friendly project with EC2 instances. To save money, you're using AWS Lambda to automatically start and stop instances when they're not needed during non-business hours. 👇
What needs to be done:
- Create an AWS Lambda function that will start/stop instances based on their instance tag.
Prerequisites
Before implementing the solution, ensure the following:
Tagged EC2 Instances
Tag Key:
AutoSchedule
Tag Value:
true
IAM Role for Lambda
Create and assign an IAM role to your Lambda function with the following permissions, or EC2 Full Access:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:DescribeInstances", "ec2:StartInstances", "ec2:StopInstances" ], "Resource": "*" } ] }
Lambda Function Code
Below is the Python code using Boto3 to start or stop EC2 instances based on the AutoSchedule
tag.
import boto3
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
action = event.get('action') # 'start' or 'stop'
if action not in ['start', 'stop']:
return {'statusCode': 400, 'body': "Invalid action."}
filters = [
{'Name': 'tag:AutoSchedule', 'Values': ['true']},
{'Name': 'instance-state-name', 'Values': ['stopped'] if action == 'start' else ['running']}
]
instances = ec2.describe_instances(Filters=filters)
instance_ids = [i['InstanceId'] for r in instances['Reservations'] for i in r['Instances']]
if not instance_ids:
return {'statusCode': 200, 'body': f"No instances to {action}."}
if action == 'start':
ec2.start_instances(InstanceIds=instance_ids)
else:
ec2.stop_instances(InstanceIds=instance_ids)
return {'statusCode': 200, 'body': f"{action.capitalize()}ed: {instance_ids}"}
Manual Testing
Before scheduling, it's important to verify the Lambda function manually.
Steps:
Navigate to your Lambda function in the AWS console.
Click Test > Create new test event.
Use the following test input:
For starting:
{ "action": "start" }
For stopping:
{ "action": "stop" }
Execute the test and check the results in the output logs.
Automating with EventBridge
To run this function at specific times daily, use EventBridge (CloudWatch Events).
Schedule to Start Instances
Go to EventBridge → Rules → Create Rule
Name:
StartEC2Instances
Schedule pattern:
cron(0 9 * * ? *)
(Every day at 9 AM UTC)Target: Your Lambda function
Input JSON:
{ "action": "start" }
Schedule to Stop Instances
Name:
StopEC2Instances
Schedule pattern:
cron(0 18 * * ? *)
(Every day at 6 PM UTC)Input JSON:
{ "action": "stop" }
Guide to set up SNS notifications for EC2 start/stop events:
Step 1: Create an SNS Topic
Open the SNS Console.
Click Create topic.
Select Standard as the topic type.
Enter the following:
- Name:
ec2-notifications
- Name:
Leave the default settings for other options and click Create topic.
Step 2: Subscribe to the Topic (Email)
After the topic is created, click on the topic name.
Click Create subscription.
Configure the subscription:
Protocol: Email
Endpoint: Enter your email address (e.g.,
you@example.com
).
Click Create subscription.
Check your email inbox and confirm the subscription by clicking the confirmation link in the email.
Step 3: Create CloudWatch/EventBridge Rule for EC2 Start & Stop Notifications
You need to create two rules: one for EC2 instance start notifications and another for EC2 instance stop notifications.
1. Create Rule for EC2 Instance Start Notification
Go to the Amazon CloudWatch Console.
In the left sidebar, select Rules under Events/EventBridge (depending on your UI version). For older UIs, navigate to Events > Rules.
Click Create Rule.
In the Rule details section:
Name:
EC2InstanceStartNotify
Description (optional):
Notify when EC2 instance starts
.
Under Event Pattern, select Event Pattern and paste the following:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["running"]
}
}
Add the target:
Click Add target.
Select SNS topic.
Choose the ec2-notifications topic you created earlier.
Click Create to finalize the rule.
2. Create Rule for EC2 Instance Stop Notification
Repeat steps 1–4 to create another rule, but with the following changes:
Name:
EC2InstanceStopNotify
Description (optional):
Notify when EC2 instance stops
.
Under Event Pattern, paste the following for EC2 stop notifications:
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["stopped"]
}
}
Add the target:
Click Add target.
Select SNS topic.
Choose the ec2-notifications topic you created earlier.
Click Create to finalize the rule.
EC2 Start Email Notification:
EC2 Stop Email Notification:
Conclusion
By combining AWS Lambda, EventBridge scheduling, and SNS notifications, you now have a fully serverless, automated framework for managing your EC2 instance lifecycle:
Cost optimization: Instances only run during business hours, reducing your hourly compute charges.
Operational visibility: SNS alerts notify you immediately whenever an instance starts or stops.
Scalability & maintainability: EventBridge cron rules and Lambda functions require no servers to manage, and you can adjust tags or schedules without changing infrastructure.
Next steps and best practices:
Review your CloudWatch Logs and SNS subscription metrics to validate that notifications are delivered as expected.
Implement IAM least-privilege for your Lambda execution role and refine tag-based permissions.
Consider adding CloudWatch alarms on Lambda errors or unexpected instance-state counts to proactively detect issues.
With these measures in place, you’ll maintain tight cost control and real-time awareness of your EC2 fleet. If you’ve adopted a similar pattern or have other ideas for optimizing AWS resource usage, I’d welcome your insights—let’s continue sharing best practices.
Subscribe to my newsletter
Read articles from Amitabh soni directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Amitabh soni
Amitabh soni
DevOps Enthusiast | Passionate Learner in Tech | BSc IT Student I’m a second-year BSc IT student with a deep love for technology and an ambitious goal: to become a DevOps expert. Currently diving into the world of automation, cloud services, and version control, I’m excited to learn and grow in this dynamic field. As I expand my knowledge, I’m eager to connect with like-minded professionals and explore opportunities to apply what I’m learning in real-world projects. Let’s connect and see how we can innovate together!