<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Philippe borribo</title>
    <description>The latest articles on DEV Community by Philippe borribo (@philippe_borribo).</description>
    <link>https://dev.to/philippe_borribo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3165494%2F601b308e-60d8-442a-bc31-445da37f5e48.png</url>
      <title>DEV Community: Philippe borribo</title>
      <link>https://dev.to/philippe_borribo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/philippe_borribo"/>
    <language>en</language>
    <item>
      <title>FinOps Optimization: Reducing AWS Bills Through Automated EC2 Shutdowns</title>
      <dc:creator>Philippe borribo</dc:creator>
      <pubDate>Fri, 16 May 2025 12:58:29 +0000</pubDate>
      <link>https://dev.to/philippe_borribo/finops-optimization-reducing-aws-bills-through-automated-ec2-shutdowns-1d9e</link>
      <guid>https://dev.to/philippe_borribo/finops-optimization-reducing-aws-bills-through-automated-ec2-shutdowns-1d9e</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;1. Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;As organizations increasingly migrate workloads to the cloud, cost management becomes a critical component of sustainable operations. While cloud services like AWS offer flexibility and scalability, they also come with the risk of escalating expenses if not carefully monitored. This is where FinOps — a practice that blends financial accountability with cloud engineering — plays a key role.&lt;br&gt;
One of the most common sources of unnecessary cloud expenditure is idle or underutilized resources, particularly Amazon EC2 instances that continue running outside of business hours. Many teams spin up instances for development, testing, or internal applications, but fail to shut them down when not in use — often because manual shutdown is inconvenient or simply forgotten.&lt;br&gt;
To address this issue, organizations can implement a simple yet powerful solution: automating the shutdown and restart of EC2 instances based on usage schedules. By stopping non-critical instances during off-hours (e.g., overnight or on weekends), companies can drastically reduce their cloud bills without compromising productivity or system availability.&lt;br&gt;
In this article, we explore how automated EC2 shutdowns can support FinOps goals through a real-world use case. We’ll break down the cost savings, demonstrate how to implement the automation, and calculate the return on investment (ROI) of this approach. Whether you're managing a startup environment or a large-scale enterprise infrastructure, the strategies discussed here can help you take meaningful control of your AWS spending.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;2. Understanding EC2 Cost Structures&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To effectively reduce AWS costs through automation, it's essential to first understand how EC2 (Elastic Compute Cloud) pricing works. AWS offers a flexible pricing model for EC2 instances, but this flexibility can also lead to overspending if not managed carefully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.1 EC2 Pricing Models&lt;/strong&gt;&lt;br&gt;
AWS provides multiple pricing options for EC2:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;On-Demand Instances: These are billed per second (with a minimum of 60 seconds) and are the most flexible option. They are ideal for short-term, unpredictable workloads, but also the most expensive if left running continuously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reserved Instances (RIs): Offer significant discounts (up to 75%) in exchange for committing to use a specific instance type in a specific region for a 1- or 3-year term. While cost-effective, they require predictable workloads and upfront planning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spot Instances: Allow you to bid on unused EC2 capacity at a reduced price — often up to 90% off. However, they can be interrupted by AWS with little notice.&lt;br&gt;
In this article, we focus on on-demand EC2 instances, as they are most commonly used in development and testing environments where usage is dynamic.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;3. Use Case Overview&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To better illustrate the practical value of automated EC2 shutdowns, let’s consider a real-world use case that many organizations can relate to: a development and testing environment running on AWS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.1 Scenario Context&lt;/strong&gt;&lt;br&gt;
A mid-sized software company uses AWS EC2 to host several environments for internal development, testing, and QA purposes. These instances are not mission-critical, and developers typically work from 05:00 to 00:00 UTC, leaving a 5-hour window each night when the machines are idle.&lt;/p&gt;

&lt;p&gt;Historically, the EC2 instances in this environment remained running 24/7, even though no one was using them during the early morning hours. This led to thousands of dollars in unnecessary compute costs over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.2 Objective&lt;/strong&gt;&lt;br&gt;
The goal of this cost-optimization initiative was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Automatically shut down all non-critical EC2 instances at midnight (00:00 UTC) and restart them at 05:00 UTC, seven days a week.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This schedule ensured that development teams would always find the environment ready when their workday began, without any delays or disruptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.3 Target Resources&lt;/strong&gt;&lt;br&gt;
The team identified which EC2 instances could be safely stopped without affecting production. To streamline this, they applied a simple tagging policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Key: AutoShutdown  
Value: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allowed the automation script to select only the relevant EC2 instances, avoiding the risk of stopping production workloads or other critical infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.4 Results Expected&lt;/strong&gt;&lt;br&gt;
By implementing this scheduled shutdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The company aimed to save at least 20% of the compute cost for each affected instance.&lt;/li&gt;
&lt;li&gt;They expected to automate the process entirely, removing reliance on manual shutdowns.&lt;/li&gt;
&lt;li&gt;The solution had to be scalable, so it could be applied to dozens (or eventually hundreds) of EC2 instances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This use case sets the stage for the technical implementation and ROI analysis that follows, demonstrating that small changes in operational discipline — when automated — can lead to significant financial impact.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;4. Automation Strategy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To achieve reliable and repeatable cost savings, the shutdown and startup of EC2 instances must be fully automated. This section outlines the tools, methodology, and implementation strategy used to automate EC2 lifecycle operations based on a fixed schedule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.1 Tools Used&lt;/strong&gt;&lt;br&gt;
A variety of tools can be used to implement EC2 automation, depending on your organization’s existing infrastructure and preferences. For this use case, we’ll focus on a simple, script-based solution using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS CLI: To interact with EC2 via terminal commands (or scripts).&lt;/li&gt;
&lt;li&gt;Crontab (Linux Scheduler): To schedule scripts to run at specific times.&lt;/li&gt;
&lt;li&gt;EC2 Instance Tags: To selectively identify which instances should be managed.&lt;/li&gt;
&lt;li&gt;IAM Roles: To securely authorize the automation script with the correct permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;For more complex or cloud-native implementations, AWS Systems Manager, Lambda, or EventBridge can be used — but here, simplicity and portability are prioritized.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4.2 Step-by-Step Implementation&lt;/strong&gt;&lt;br&gt;
&lt;u&gt;Step 1: Tag Your EC2 Instances&lt;/u&gt;&lt;br&gt;
Add a custom tag to all EC2 instances that should be included in the shutdown/startup cycle. &lt;br&gt;
For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Key: AutoShutdown
Value: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tag will serve as a filter for the automation script.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Step 2: Create IAM Permissions&lt;/u&gt;&lt;br&gt;
Ensure the script (or the instance running the script) has an IAM role or user with at least the following permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeInstances",
        "ec2:StopInstances",
        "ec2:StartInstances"
      ],
      "Resource": "*"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;u&gt;Step 3: Write the Shutdown Script&lt;/u&gt;&lt;br&gt;
Here’s an example in Bash using AWS CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Get instance IDs of EC2s with the tag AutoShutdown=true and that are running
INSTANCES=$(aws ec2 describe-instances \
  --filters "Name=tag:AutoShutdown,Values=true" "Name=instance-state-name,Values=running" \
  --query "Reservations[*].Instances[*].InstanceId" --output text)

if [ -z "$INSTANCES" ]; then
  echo "No instances to stop."
else
  echo "Stopping instances: $INSTANCES"
  aws ec2 stop-instances --instance-ids $INSTANCES
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;u&gt;Step 4: Write the Startup Script&lt;/u&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Get instance IDs of EC2s with the tag AutoShutdown=true and that are stopped
INSTANCES=$(aws ec2 describe-instances \
  --filters "Name=tag:AutoShutdown,Values=true" "Name=instance-state-name,Values=stopped" \
  --query "Reservations[*].Instances[*].InstanceId" --output text)

if [ -z "$INSTANCES" ]; then
  echo "No instances to start."
else
  echo "Starting instances: $INSTANCES"
  aws ec2 start-instances --instance-ids $INSTANCES
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These scripts can be placed on a dedicated automation instance, or embedded into a lightweight management server.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Step 5: Schedule with Crontab&lt;/u&gt;&lt;br&gt;
Use crontab -e to schedule the jobs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Stop instances every day at 00:00 UTC
0 0 * * * /path/to/stop-ec2.sh &amp;gt;&amp;gt; /var/log/ec2_stop.log 2&amp;gt;&amp;amp;1

# Start instances every day at 05:00 UTC
0 5 * * * /path/to/start-ec2.sh &amp;gt;&amp;gt; /var/log/ec2_start.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure the environment running these cron jobs has valid AWS credentials or an appropriate IAM role attached.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.3 Error Handling and Logging&lt;/strong&gt;&lt;br&gt;
To ensure reliability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add logging to capture success/failure of each operation.&lt;/li&gt;
&lt;li&gt;Use email alerts or Slack/webhook notifications for failed jobs (optional).&lt;/li&gt;
&lt;li&gt;Use AWS CloudWatch Logs or a central syslog server for log aggregation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4.4 Scalability Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As the environment grows, you can switch to AWS Lambda + EventBridge for more scalable, serverless management.&lt;/li&gt;
&lt;li&gt;For production environments, consider using State Manager in AWS Systems Manager to enforce desired instance states at scale.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By automating EC2 management with lightweight tools and best practices, organizations can ensure cost savings are applied consistently and securely, without adding operational overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. Risks and Considerations&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While automating the shutdown and startup of EC2 instances is an effective FinOps strategy, it's not without potential challenges. Failing to account for these risks could lead to service interruptions, data loss, or operational inefficiencies. This section outlines the key considerations every organization should evaluate before deploying an EC2 automation policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.1 Risk of Stopping Critical Instances&lt;/strong&gt;&lt;br&gt;
The biggest risk in automated shutdowns is inadvertently stopping production or critical infrastructure. If an instance that supports live services is mistakenly tagged (or not properly excluded), it could result in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service downtime&lt;/li&gt;
&lt;li&gt;User disruption&lt;/li&gt;
&lt;li&gt;Violation of SLAs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mitigation Strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use strict tagging policies with defined naming conventions (AutoShutdown=true only on non-critical resources).&lt;/li&gt;
&lt;li&gt;Maintain a list of "Do Not Touch" tags (NoShutdown=true or Critical=true) to exclude sensitive resources.&lt;/li&gt;
&lt;li&gt;Implement a manual approval workflow for newly tagged instances before they are included in automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5.2 Delayed Availability at Startup&lt;/strong&gt;&lt;br&gt;
Even when automation works as expected, there may be a delay in instance availability due to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Boot time for the OS and applications&lt;/li&gt;
&lt;li&gt;Service warm-up (e.g., databases or backend processes)&lt;/li&gt;
&lt;li&gt;Dependency resolution (e.g., connections to external services)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For instance, a large EC2 instance running a containerized microservice might take 3–5 minutes to fully initialize.&lt;/p&gt;

&lt;p&gt;Mitigation Strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build startup buffers into the schedule (e.g., restart instances at 04:45 instead of 05:00).&lt;/li&gt;
&lt;li&gt;Use health checks to confirm service readiness.&lt;/li&gt;
&lt;li&gt;Leverage pre-warming scripts that prepare the environment immediately after the instance boots.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5.3 Incomplete or Inconsistent Tagging&lt;/strong&gt;&lt;br&gt;
Automation relies on accurate and consistent tagging. In practice, many environments suffer from tagging drift, where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instances are launched without appropriate tags.&lt;/li&gt;
&lt;li&gt;Old instances retain outdated or incorrect tags.&lt;/li&gt;
&lt;li&gt;Developers bypass policies due to lack of enforcement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mitigation Strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enforce tagging at provisioning time using IAM policies, &lt;/li&gt;
&lt;li&gt;Service Control Policies (SCPs), or Infrastructure-as-Code (IaC) templates like Terraform or CloudFormation.&lt;/li&gt;
&lt;li&gt;Periodically run audit scripts to detect untagged or misconfigured resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use AWS Config rules or Tag Policies in AWS Organizations to maintain compliance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.4 Security and Permissions Misconfiguration&lt;/strong&gt;&lt;br&gt;
Automated scripts require IAM permissions. Poorly scoped permissions can either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expose security vulnerabilities (if overly permissive), or&lt;/li&gt;
&lt;li&gt;Break the automation (if too restrictive)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mitigation Strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow the principle of least privilege when defining IAM roles.&lt;/li&gt;
&lt;li&gt;Use instance profiles instead of hardcoded credentials.&lt;/li&gt;
&lt;li&gt;Regularly rotate keys and audit IAM policies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5.5 Dependency on a Single Point of Failure&lt;/strong&gt;&lt;br&gt;
If the automation relies on a single server (e.g., a Linux VM running cron jobs), its failure could break the entire process.&lt;/p&gt;

&lt;p&gt;Mitigation Strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use high-availability setups or run scripts from AWS Lambda.&lt;/li&gt;
&lt;li&gt;Monitor task success/failure using CloudWatch alarms, email alerts, or observability tools.&lt;/li&gt;
&lt;li&gt;Keep manual override scripts available to quickly restart or stop instances if needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5.6 Compliance and Auditability&lt;/strong&gt;&lt;br&gt;
In regulated environments, automated changes must be traceable. Stopping or starting instances without proper logging could violate audit requirements.&lt;/p&gt;

&lt;p&gt;Mitigation Strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable CloudTrail to log all EC2 actions (stop/start/terminate).&lt;/li&gt;
&lt;li&gt;Centralize logs in CloudWatch Logs or a SIEM for review.&lt;/li&gt;
&lt;li&gt;Document the automation policy and keep it aligned with governance frameworks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;6. Best Practices for EC2 Cost Optimization&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Successfully automating the shutdown and startup of EC2 instances is only the beginning. To sustain the benefits and avoid backsliding into inefficient usage, organizations must adopt a set of operational and cultural best practices. This section provides practical guidance for embedding EC2 automation into your long-term FinOps and cloud governance strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6.1 Establish a Strong Tagging Policy&lt;/strong&gt;&lt;br&gt;
Tagging is the backbone of instance targeting for automation. A consistent, enforced tagging strategy helps you scale cost-saving efforts and reduce errors.&lt;/p&gt;

&lt;p&gt;Recommendations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define required tags such as:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;AutoShutdown=true&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Environment=dev/test/prod&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Owner=team-name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CostCenter=12345&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use AWS Tag Policies and IAM tag enforcement rules to ensure compliance.&lt;/li&gt;
&lt;li&gt;Automate tagging through Infrastructure as Code (IaC) templates like Terraform, CloudFormation, or Pulumi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6.2 Involve DevOps and Developers Early&lt;/strong&gt;&lt;br&gt;
Automation policies should be collaborative, not imposed. Developers and DevOps engineers often know which workloads are safe to shut down — and which are not.&lt;/p&gt;

&lt;p&gt;Tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Involve teams in identifying auto-shutdown candidates.&lt;/li&gt;
&lt;li&gt;Provide them with tooling or dashboards to opt in/out.&lt;/li&gt;
&lt;li&gt;Educate teams about the cost impact of idle resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6.3 Use AWS Native Services for Scaling&lt;/strong&gt;&lt;br&gt;
While shell scripts and crontabs work well for small-scale environments, growing organizations benefit from AWS-native, serverless automation.&lt;/p&gt;

&lt;p&gt;Advanced options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS EventBridge: Schedule events to trigger instance actions.&lt;/li&gt;
&lt;li&gt;AWS Lambda: Run scripts without managing infrastructure.&lt;/li&gt;
&lt;li&gt;AWS Systems Manager Automation Documents (SSM): Define and execute EC2 stop/start workflows with tracking and audit logs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These services are more resilient, monitorable, and maintainable over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6.4 Track Savings with Tag-Based Cost Allocation&lt;/strong&gt;&lt;br&gt;
Use AWS Cost Explorer and Cost Allocation Tags to measure the financial impact of your automation initiative.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Activate the AutoShutdown tag in the AWS billing console.&lt;/li&gt;
&lt;li&gt;Use Cost Explorer filters to compare costs before and after implementation.&lt;/li&gt;
&lt;li&gt;Present monthly reports to stakeholders showing realized savings per instance, team, or environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reinforces accountability and justifies future FinOps investments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6.5 Monitor and Iterate&lt;/strong&gt;&lt;br&gt;
Automation is not a "set it and forget it" strategy. EC2 usage evolves, new teams spin up instances, and requirements change.&lt;/p&gt;

&lt;p&gt;Recommendations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set up alerts and monitoring to track failed or missed shutdowns.&lt;/li&gt;
&lt;li&gt;Schedule quarterly reviews to refine automation rules and schedules.&lt;/li&gt;
&lt;li&gt;Maintain documentation and onboarding guides for new teams.&lt;/li&gt;
&lt;li&gt;Use automation scripts stored in version control (e.g., GitHub, CodeCommit) to enable version tracking and collaborative updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6.6 Integrate into Broader FinOps Practice&lt;/strong&gt;&lt;br&gt;
Automating EC2 shutdowns should be part of a larger FinOps maturity model, which may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rightsizing instances&lt;/li&gt;
&lt;li&gt;Buying Reserved Instances or Savings Plans&lt;/li&gt;
&lt;li&gt;Deleting unused volumes or snapshots&lt;/li&gt;
&lt;li&gt;Optimizing S3 storage tiers&lt;/li&gt;
&lt;li&gt;Tracking per-project or per-department costs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By integrating EC2 scheduling into a FinOps culture, organizations can align cloud usage with business value.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;7. Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Automating the shutdown and startup of EC2 instances may seem like a simple technical task, but it represents a powerful and scalable FinOps strategy with measurable impact. By reducing idle compute time especially outside business hours. Organizations can unlock significant cost savings without compromising performance or productivity.&lt;br&gt;
As demonstrated, this approach requires more than a few lines of script: it calls for a disciplined framework involving tagging policies, stakeholder alignment, security governance, and continuous monitoring. When combined with AWS-native tools and a culture of cloud cost awareness, EC2 automation becomes a key pillar of operational efficiency.&lt;br&gt;
Ultimately, the success of any cost optimization initiative depends not just on the tools you use, but on how consistently and intelligently you apply them. With the right practices in place, automated EC2 scheduling can serve as a launchpad for broader FinOps maturity... transforming cloud infrastructure from a cost center into a strategic advantage.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>finops</category>
      <category>automation</category>
      <category>crontab</category>
    </item>
    <item>
      <title>Never get caught off guard: Receive your server's health every minute by Email</title>
      <dc:creator>Philippe borribo</dc:creator>
      <pubDate>Thu, 15 May 2025 08:17:16 +0000</pubDate>
      <link>https://dev.to/philippe_borribo/never-get-caught-off-guard-receive-your-servers-health-every-minute-by-email-412f</link>
      <guid>https://dev.to/philippe_borribo/never-get-caught-off-guard-receive-your-servers-health-every-minute-by-email-412f</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For system administrators, surprises are rarely a good thing. Whether it's a sudden spike in CPU usage, memory running dangerously low, or disk space nearing its limit, these issues can quickly escalate into major problems : from system slowdowns to full outages.&lt;br&gt;
The key to avoiding such disasters? Proactive monitoring.&lt;br&gt;
Imagine receiving a quick health check of your server every single minute: delivered straight to your inbox. No need to log in and manually check metrics. Instead, you stay one step ahead, spotting trouble before it affects users or services.&lt;br&gt;
In this article, you'll learn how to set up a simple but powerful script that runs automatically every minute. It collects key system metrics like CPU, memory, and disk usage, then emails the report to your system administrator. It's fast, lightweight, and incredibly effective - a perfect fit for anyone managing production environments or personal servers alike.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;1. Why monitor your server every minute?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When it comes to server health, timing is everything. Even a few minutes of downtime can have serious consequences… from lost revenue to broken user trust. While traditional monitoring solutions may check system status every 5 or 10 minutes, some environments require faster feedback and immediate awareness.&lt;br&gt;
&lt;strong&gt;a. Real-Time awareness&lt;/strong&gt;&lt;br&gt;
Monitoring your server every minute gives you near real-time visibility into its behavior. This is especially useful for detecting:&lt;br&gt;
Sudden CPU spikes due to rogue processes.&lt;br&gt;
Memory leaks that gradually degrade performance.&lt;br&gt;
Rapid disk consumption caused by logging errors, backups, or attacks.&lt;br&gt;
By checking these metrics every 60 seconds, you drastically reduce the time between a problem appearing and it being detected.&lt;br&gt;
&lt;strong&gt;b. Faster incident response&lt;/strong&gt;&lt;br&gt;
Early detection means faster reaction. If you receive an email showing high CPU usage or critical memory shortage, you can investigate and act before the issue escalates into service disruption. In production environments, this can save hours of downtime and avoid emergency interventions.&lt;br&gt;
&lt;strong&gt;c. Lightweight alternative to complex monitoring tools&lt;/strong&gt;&lt;br&gt;
While tools like Nagios, Zabbix, or Prometheus are powerful, they can be overkill for smaller setups or individual servers. A simple script combined with a cron job offers a minimalist approach to monitoring - no dashboards, no agents, no third-party services - just email notifications that work.&lt;br&gt;
&lt;strong&gt;d. Ideal for headless or remote servers&lt;/strong&gt;&lt;br&gt;
If you're managing cloud instances, VPS setups, or physical servers in remote locations, having frequent performance reports in your inbox provides peace of mind. You're always informed, even when you're away from the terminal.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;2. What metrics should be tracked?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To keep your server healthy and responsive, it's important to track a few key performance indicators. These metrics provide a snapshot of your system's current state and help you spot problems before they become critical.&lt;br&gt;
Here are the most essential metrics you should include in your monitoring script:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. CPU usage&lt;/strong&gt;&lt;br&gt;
CPU usage shows how much of your processor's capacity is being used at a given moment. High or constantly maxed-out CPU usage can indicate:&lt;br&gt;
Inefficient code or processes running in loops&lt;br&gt;
Malware or unauthorized scripts&lt;br&gt;
Overloaded services during peak traffic&lt;/p&gt;

&lt;p&gt;You can retrieve this metric using commands like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;top -bn1 | grep "Cpu(s)"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or more simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mpstat 1 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;b. Memory usage&lt;/strong&gt;&lt;br&gt;
Memory consumption is another critical metric. If your system runs out of RAM, it will start using swap space, which is significantly slower and can cause serious performance degradation.&lt;br&gt;
Track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Total memory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Used memory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Free memory&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swap usage&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Command example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;free -m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;c. Disk usage&lt;/strong&gt;&lt;br&gt;
Running out of disk space can crash applications, break databases, or prevent logging. Your script should report:&lt;br&gt;
Total and used space per mounted partition&lt;br&gt;
Alert thresholds (e.g., warn if a partition is over 90%)&lt;/p&gt;

&lt;p&gt;Use this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df -h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;d. Optional: load average&lt;/strong&gt;&lt;br&gt;
The load average reflects how many processes are actively running or waiting for CPU time. It gives a broader view of overall system strain.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uptime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cat /proc/loadavg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;e. Optional: Uptime and reboot detection&lt;/strong&gt;&lt;br&gt;
Knowing how long your server has been running helps identify unexpected reboots or instability.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uptime -p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;3. Tools You'll Need&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Setting up an automated monitoring script that sends email reports every minute doesn't require complex infrastructure or expensive software. All you need are a few standard tools, most of which are already available on typical Linux distributions. Here's a breakdown of what you'll need and why:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. A Linux server&lt;/strong&gt;&lt;br&gt;
This guide assumes you're running a Unix-based system like Ubuntu, Debian, CentOS, or Red Hat. Most cloud instances (AWS, Azure, DigitalOcean, etc.) run some flavor of Linux. The commands and tools used are native to these environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;b. A Scripting Language (Bash or Python)&lt;/strong&gt;&lt;br&gt;
You'll need a script that collects system metrics and formats them into an email message.&lt;br&gt;
Bash is ideal for simplicity and direct access to system commands.&lt;br&gt;
Python offers more flexibility, better formatting options, and error handling.&lt;br&gt;
Choose the one you're more comfortable with - both are excellent for the task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;c. Crontab&lt;/strong&gt;&lt;br&gt;
cron is the time-based job scheduler built into Linux. It allows you to run scripts at fixed intervals… like every minute. &lt;br&gt;
To edit the scheduled jobs, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crontab -e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where you'll tell the system to execute your monitoring script regularly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;d. Mail Utility (mailx, msmtp, or sendmail)&lt;/strong&gt;&lt;br&gt;
To send system emails, your server needs a mail transfer agent (MTA) or a mail client that can send messages from the command line.&lt;br&gt;
Some options include:&lt;br&gt;
mailx: Simple and commonly pre-installed. Often used with sendmail or postfix.&lt;br&gt;
msmtp: Lightweight and easy to configure with an external SMTP service (like Gmail).&lt;br&gt;
sendmail or postfix: Full-fledged MTAs but heavier to configure.&lt;/p&gt;

&lt;p&gt;For example, to install msmtp on Ubuntu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install msmtp msmtp-mta
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a configuration file ~/.msmtprc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano ~/.msmtprc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And add your SMTP credentials&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile ~/.msmtp.log
account gmail
host smtp.gmail.com
port 587
from your.email@gmail.com
user your.email@gmail.com
password your_app_password
account default : gmail
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;e. A Valid Email Address for Delivery&lt;/strong&gt;&lt;br&gt;
In your script, you'll specify the recipient email.&lt;br&gt;
Make sure:&lt;br&gt;
The email is actively monitored.&lt;br&gt;
SMTP settings are correct to ensure deliverability.&lt;br&gt;
You whitelist your server's address, if needed, to avoid spam filters&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;4. Writing the Monitoring Script&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that you know what metrics to track and which tools to use, it's time to write the core of the solution - the monitoring script. This script will collect the server's CPU, memory, and disk usage data, format it into a readable message, and send it to the system administrator via email.&lt;br&gt;
We'll write a simple Bash script, which is efficient and widely compatible across Linux distributions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;a. Script Overview&lt;/strong&gt;&lt;br&gt;
The script will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Collect system performance metrics (CPU, RAM, Disk).&lt;/li&gt;
&lt;li&gt;Format the data into a plain-text report.&lt;/li&gt;
&lt;li&gt;Email the report to the system administrator.&lt;/li&gt;
&lt;li&gt;Optionally include a timestamp and hostname.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;b. Sample script (monitor.py)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import psutil
import socket
import datetime
import subprocess

# Collect system metrics
def get_metrics():
    hostname = socket.gethostname()
    cpu = psutil.cpu_percent(interval=1)
    ram = psutil.virtual_memory()
    disk = psutil.disk_usage('/')
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    message = f"""\
Subject: [ALERT] Server Metrics - {hostname}
From: Monitoring &amp;lt;monitor@localhost&amp;gt;
To: your@email.com

Date       : {now}
Server     : {hostname}

CPU     : {cpu}% used
RAM     : {ram.percent}% used ({round(ram.used / (1024**3), 2)} GB / {round(ram.total / (1024**3), 2)} GB)
Disk    : {disk.percent}% used ({round(disk.used / (1024**3), 2)} GB / {round(disk.total / (1024**3), 2)} GB)
"""
    return message

# Send the email using msmtp
def send_email(body):
    process = subprocess.Popen(
        ['msmtp', 'destination@email.com'],
        stdin=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    stdout, stderr = process.communicate(input=body.encode())

    if process.returncode != 0:
        print("Failed to send email:", stderr.decode())
    else:
        print("Email sent successfully.")

# Main
if __name__ == "__main__":
    metrics = get_metrics()
    send_email(metrics)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;c. Make the Script Executable&lt;/strong&gt;&lt;br&gt;
Save the script as monitor.py, then make it executable:&lt;br&gt;
chmod +x monitor.py&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;d. Test the Script&lt;/strong&gt;&lt;br&gt;
Run it manually first to ensure it works as expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python monitor.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zu9k091kmpx1lwk50o6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zu9k091kmpx1lwk50o6.png" alt="Image description" width="800" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check the recipient inbox (or spam folder if necessary) to confirm receipt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg119zztn2hhf6tq3jai2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg119zztn2hhf6tq3jai2.png" alt="Image description" width="800" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. Automating the Script with Crontab&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To send metrics every minute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crontab -e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* * * * * python monitor.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Automating the monitoring of server health is not just a good practice, it's essential for maintaining system reliability, identifying performance issues early, and preventing downtime. With a simple Bash script, a few core Linux tools, and a properly configured email system, you can build a lightweight but powerful alerting mechanism that keeps your system administrator informed every minute.&lt;br&gt;
This approach doesn't require expensive monitoring platforms or complex dashboards. It leverages native system utilities and the flexibility of cron to deliver real-time performance snapshots directly to the sysadmin's inbox. By tracking key metrics such as CPU usage, memory consumption, and disk space, you create a proactive culture of system care rather than waiting for something to break.&lt;br&gt;
In environments where uptime and responsiveness matter, such a script can be the first line of defense… a quiet guardian running in the background, ensuring your infrastructure stays healthy and your admin stays informed.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>python</category>
      <category>automation</category>
      <category>monitoring</category>
    </item>
  </channel>
</rss>
