Back to blog
AWS

How We Reduced AWS Costs by 15% with Automated EC2 Hibernation

AWS bills have a way of growing faster than the infrastructure that generates them. On a recent engagement with a fintech client running workloads across multiple AWS accounts, we identified that a significant portion of their EC2 spend was on instances running during off-hours — dev/staging environments, batch processing nodes, and internal tools that nobody used between 8 PM and 8 AM.

The solution was straightforward: automated EC2 hibernation and stop/start scheduling using Terraform and Lambda. The result was a 10-15% reduction in their monthly AWS bill.

The Problem: Always-On Is Expensive

The client had roughly 200 EC2 instances across 4 AWS accounts. About 40% of these were non-production workloads — development environments, QA clusters, staging replicas, and internal dashboards. These instances ran 24/7 despite being actively used only during business hours (roughly 10 hours/day on weekdays).

Quick math: running an instance 24/7 costs 168 hours/week. If it is only needed for 50 hours/week, you are paying for 118 hours of idle time — 70% waste.

The Solution: Tag-Based Scheduling with Lambda

Rather than building a complex scheduling system, we implemented a lightweight, tag-based approach:

Step 1: Define scheduling tags

We added two tags to EC2 instances:

  • Schedule: business-hours — stop at 8 PM IST, start at 8 AM IST, weekdays only
  • Schedule: extended — stop at 11 PM, start at 7 AM, all days
  • No tag = always on (production workloads)

Step 2: Lambda functions for start/stop

Two Lambda functions handled the automation:

  • StopInstances — queries EC2 for running instances with a matching Schedule tag, then stops or hibernates them
  • StartInstances — queries for stopped/hibernated instances with matching tags and starts them

We chose hibernation over stop/start where possible because hibernation preserves in-memory state, making resume faster and avoiding cold-start issues for development environments.

Step 3: EventBridge rules for scheduling

CloudWatch EventBridge (cron) rules triggered the Lambda functions at the defined times. Each schedule profile had its own pair of rules.

Step 4: Terraform for everything

The entire setup — Lambda functions, IAM roles, EventBridge rules, and tag policies — was defined in Terraform. This meant:

  • The scheduling infrastructure itself was version-controlled and reproducible
  • Adding a new schedule profile required only a new Terraform variable, not code changes
  • The same module was deployed across all 4 AWS accounts

Multi-Account Strategy

The client used AWS Organizations with separate accounts for dev, staging, production, and shared services. We deployed the scheduling Lambda in the shared services account and used cross-account IAM roles to manage instances in the other accounts.

This centralized approach meant:

  • One place to manage all scheduling logic
  • Consistent tagging policies enforced via AWS Config rules
  • A single CloudWatch dashboard showing cost impact across all accounts

Handling Edge Cases

The simple approach works well, but production taught us a few lessons:

  • Override mechanism — engineers sometimes need instances during off-hours. We added an Override: keep-running tag that the Lambda functions respect, with a TTL that auto-removes the override after 24 hours
  • RDS instances — we extended the same pattern to RDS instances in non-production accounts, stopping dev databases during off-hours
  • EBS volumes — stopped instances still incur EBS costs. For truly ephemeral dev environments, we switched to instance store volumes where possible
  • Elastic IPs — stopped instances with allocated EIPs incur charges. We automated EIP release/allocation as part of the stop/start cycle

Results

After one month of running the scheduling automation:

  • 10-15% reduction in total EC2 spend across all accounts
  • Zero impact on developer productivity — instances were available during all working hours
  • Faster dev environments — hibernation preserved state, so developers resumed exactly where they left off
  • Better resource awareness — the tagging exercise itself revealed orphaned instances and unused resources

Key Takeaways

  • Start with tagging — you cannot optimize what you cannot categorize
  • Lambda + EventBridge is the simplest scheduling architecture on AWS
  • Hibernation is preferable to stop/start for developer experience
  • Deploy scheduling infrastructure with Terraform, not ClickOps
  • Multi-account setups benefit from centralized scheduling with cross-account roles
  • Always provide an override mechanism for engineers who need off-hours access

Cost optimization does not require complex tools or third-party platforms. A well-designed tagging strategy and a few Lambda functions can deliver significant savings with minimal operational overhead.

Want to reduce your AWS costs?

Book a 30-minute architecture review and get actionable recommendations.

Book an architecture review