CloudBudgetMasterCloudBudgetMaster

← All articles

Strategy

Advanced Cloud Cost Optimization Strategy Teams Miss

October 20, 2026·6 min read·CloudBudgetMaster

Why an overlooked tactic matters

Most engineering and platform teams focus on rightsizing instances, using Reserved Instances or Spot, and cleaning up obvious orphaned resources. Those actions capture the low‑ hanging fruit, but a large portion of waste lives in resources that are idle for hours or days and then automatically start again. If a development environment is left running overnight, or a test database is spun up by a CI pipeline and never terminated, the bill grows silently. The tactic most teams miss is to combine AWS Compute Optimizer insights with an automated shutdown workflow driven by Lambda and CloudWatch Events. By detecting idle patterns, tagging resources, and scheduling stop/start actions, you can eliminate waste without manual intervention.

Understand idle resource patterns with AWS Compute Optimizer

Enable Compute Optimizer

  1. Open the AWS Management Console.
  2. Navigate to Services → Compute Optimizer.
  3. Choose Get started and select the resource types you want to analyze (EC2, Auto Scaling groups, EBS, Lambda).
  4. Click Enable. The service begins collecting performance metrics for up to 14 days.

You can also enable via CLI:

aws compute-optimizer update-enrollment-status \
  --status Active \
  --resource-types EC2 AutoScalingGroup EBS Lambda

Interpreting recommendations

After the data collection period, Compute Optimizer provides a recommendation list. Look for entries with the Utilization column below 20 % and the Recommendation type set to Stop or Downsize. Export the list for further processing:

aws compute-optimizer get-recommendations \
  --service EC2 \
  --output json > ec2-recs.json

The JSON contains the instance ID, current configuration, and a suggested action. Filter the results with jq to keep only low‑utilization instances:

jq '.instanceRecommendations[] | select(.utilizationMetrics[].value < 20)' ec2-recs.json > low-util.json

These IDs become the input for the automated shutdown workflow.

Automate idle shutdown with Instance Scheduler and Lambda

Create an IAM role for the Lambda function

aws iam create-role \
  --role-name IdleShutdownLambdaRole \
  --assume-role-policy-document file://trust-policy.json

trust-policy.json should contain:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "lambda.amazonaws.com"},
    "Action": "sts:AssumeRole"
  }]
}

Attach the following policy to allow stopping instances:

aws iam put-role-policy \
  --role-name IdleShutdownLambdaRole \
  --policy-name StopInstancesPolicy \
  --policy-document file://stop-policy.json

stop-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["ec2:StopInstances", "ec2:DescribeInstances"],
    "Resource": "*"
  }]
}

Deploy a CloudWatch Event rule to trigger the Lambda daily

aws events put-rule \
  --name DailyIdleShutdown \
  --schedule-expression "cron(0 2 * * ? *)" \
  --state ENABLED

The cron expression runs the rule at 02:00 UTC each day. Add the Lambda target:

aws events put-targets \
  --rule DailyIdleShutdown \
  --targets "Id"="1","Arn"="arn:aws:lambda:us-east-1:123456789012:function:IdleShutdown"

Grant EventBridge permission to invoke the function:

aws lambda add-permission \
  --function-name IdleShutdown \
  --statement-id EventBridgeInvoke \
  --action "lambda:InvokeFunction" \
  --principal events.amazonaws.com \
  --source-arn "arn:aws:events:us-east-1:123456789012:rule/DailyIdleShutdown"

Lambda function code (Python 3.9)

Save the following as lambda_function.py and zip it with any dependencies.

import boto3
import json
import os

ec2 = boto3.client('ec2')

def lambda_handler(event, context):
    # Load the list of low‑utilization instance IDs from S3 or Parameter Store
    # For simplicity, we use a hard‑coded list here
    instance_ids = os.getenv('INSTANCE_IDS', '').split(',')
    if not instance_ids:
        print('No instances to stop')
        return {'statusCode': 200}
    response = ec2.stop_instances(InstanceIds=instance_ids)
    print('Stopped instances:', response)
    return {'statusCode': 200, 'body': json.dumps(response)}

Set the environment variable INSTANCE_IDS with a comma‑separated list generated from the Compute Optimizer export. You can automate that step with a daily Step Functions workflow, but the core idea is that the Lambda stops only the resources identified as idle.

Tag‑driven cost control: using cost allocation tags to drive automation

Define a tag policy for idle detection

Create a tag key called IdleCheck with values true or false. Enforce the tag on all new EC2 instances via an AWS Config rule:

aws configservice put-config-rule \
  --config-rule-name enforce-idle-tag \
  --source "Owner=AWS,SourceIdentifier=REQUIRED_TAGS" \
  --input-parameters '{"tagKey":"IdleCheck"}'

When an instance is launched, set IdleCheck=true. The Lambda function can then filter on this tag before issuing a stop command, ensuring that critical production instances are never stopped unintentionally.

Use Cost Explorer for tag‑based alerts

  1. Open Cost Explorer → Cost allocation tags.
  2. Activate the IdleCheck tag.
  3. Create a budget under Budgets → Create budget.
  4. Choose Cost budget, select the IdleCheck tag, and set a threshold (e.g., $50 per month).
  5. Enable Alert and configure the notification to an SNS topic that triggers the same Lambda to run a tighter scan.

This feedback loop keeps the idle‑resource list fresh and aligns cost alerts with the automation.

Manual vs automated shutdown: a quick comparison

Aspect Manual shutdown Automated Lambda workflow
Human effort Requires daily login, identification, and stop action Runs on schedule without human interaction
Accuracy Prone to missed instances or accidental termination Uses Compute Optimizer data and tags to target only low‑utilization resources
Speed of response Hours to days after waste is identified Immediate after the daily rule fires
Scalability Not practical beyond a few dozen instances Handles thousands of resources across accounts
Auditing Manual logs or screenshots Centralized CloudWatch logs and Lambda metrics

Integrate with CloudBudgetMaster’s free AWS waste finder

Before you build the automation, get a baseline view of waste with the free AWS waste finder. The tool scans your account in read‑only mode and lists idle resources with an estimated dollar impact. Use that report to validate the Compute Optimizer recommendations and to seed the initial INSTANCE_IDS list for the Lambda function.

Frequently asked questions

How often should Compute Optimizer data be refreshed?

Compute Optimizer collects metrics continuously, but recommendations are refreshed every 24 hours. Running the export and Lambda workflow once per day captures the latest idle patterns.

Will stopping an instance affect data on attached EBS volumes?

Stopping an EC2 instance preserves the root and attached EBS volumes. The data remains intact and you are billed only for the storage, not for compute.

Can this approach be used for RDS or Redshift?

The same principle applies, but you need to call rds:StopDBInstance or redshift:PauseCluster APIs. Adjust the Lambda code and IAM policy accordingly.

What if an instance is needed for a scheduled job later in the day?

Add a tag ResumeAt with a timestamp and extend the Lambda to start instances whose ResumeAt time has passed. This creates a start‑stop cycle that matches your workload schedule.

Key takeaways

CloudBudgetMaster automates this. It scans AWS read‑only today, reports the dollar impact of idle and wasted resources, and will add GCP, Azure and Snowflake support soon. To try it, create a free account.

Stop guessing where your AWS bill comes from

Upload a CSV, no signup. CloudBudgetMaster finds idle, unused, and overspending AWS resources automatically. GCP and Azure coming soon.

Run a free check