CloudBudgetMasterCloudBudgetMaster

← All articles

Strategy

Advanced Cloud Cost Optimization Strategy Most Teams Overlook

September 14, 2026·9 min read·CloudBudgetMaster

The hidden cost of idle resources and why most teams miss it

Most cloud‑cost checklists focus on obvious levers: reserved instances, rightsizing, and storage tiering. Those actions capture low‑ hanging fruit, but they leave a persistent source of waste—idle compute that remains running because no one has a process to turn it off. The problem is not just a few forgotten EC2 instances; it is a systemic gap in how teams manage temporal workloads across multiple accounts and regions. When a resource is only needed during business hours, on‑call rotations, or scheduled batch windows, leaving it running 24/7 adds dollars to the bill without delivering value.

The advanced strategy that many organizations overlook is combining AWS Compute Optimizer recommendations with automated instance scheduling. Compute Optimizer tells you which instances are under‑utilized, while an instance‑scheduler (either the AWS‑provided solution or a custom Lambda workflow) enforces a start/stop policy based on tags. Together they create a feedback loop that continuously identifies waste and removes it without manual intervention.

Below is a step‑by‑step guide that engineers, founders, and platform teams can follow today. All commands are copy‑paste ready, and every console path is listed so you can verify the configuration.

Prerequisites and account preparation

Before you implement the automated scheduling loop, make sure the following are in place:

  1. Read‑only IAM role that can access Compute Optimizer, CloudWatch, and EC2 APIs. If you already have a FinOps or Cloud‑Ops role, add the following managed policies: - ComputeOptimizerReadOnlyAccess - AmazonEC2ReadOnlyAccess - CloudWatchReadOnlyAccess
  2. AWS CLI version 2 installed and configured with the read‑only role: bash aws configure set role_arn arn:aws:iam::123456789012:role/FinOpsReadOnly aws configure set source_profile default
  3. Tagging discipline – decide on a tag key that signals a schedule, e.g., Schedule=business-hours. Document the tag in your internal wiki so developers know how to opt‑in.
  4. Centralized logging – enable CloudTrail in all accounts and regions you plan to scan. This is required for Compute Optimizer to collect usage data.

Step 1 – Enable AWS Compute Optimizer across accounts

Compute Optimizer needs at least 14 days of usage data to generate reliable recommendations. Enabling it once per organization is enough; the service automatically discovers new accounts linked via AWS Organizations.

  1. Open the AWS Management ConsoleCompute OptimizerSettings.
  2. Click Enable and select All accounts and All regions.
  3. Confirm the IAM role you created in the prerequisites has ComputeOptimizerReadOnlyAccess.
  4. (Optional) Use the CLI to enable it programmatically: bash aws compute-optimizer update-enrollment-status \ --status Active \ --region us-east-1

Tip: After enabling, give the service 24‑48 hours to ingest data before pulling recommendations.

Step 2 – Pull under‑utilized instance recommendations

Once Compute Optimizer has data, you can retrieve a list of instances that are consistently below a utilization threshold (e.g., CPU < 20% and Memory < 30%).

aws compute-optimizer get-recommendations \
    --account-ids 123456789012 \
    --service EC2Instance \
    --filters name=UtilizationMetric,values=CPUUtilization,MemoryUtilization \
    --max-results 1000 \
    --query "recommendations[?utilizationMetrics[?value<`20`]].{InstanceId:instanceArn,CurrentType:instanceType,RecommendedType:recommendedInstanceType}" \
    --output table

The output shows each instance ARN, its current type, and the recommended smaller type. Export the list to a CSV for the next step:

aws compute-optimizer get-recommendations \
    --service EC2Instance \
    --output json > recommendations.json
jq -r '.recommendations[] | [.instanceArn, .instanceType, .recommendedInstanceType] | @csv' recommendations.json > recommendations.csv

Step 3 – Tag instances for scheduled shutdown

The automation works on a tag‑driven model. Add the Schedule=business-hours tag to any instance you want to stop outside of working hours. You can bulk‑tag using the CSV from the previous step.

while IFS=, read -r arn current recommended; do
  instance_id=$(echo $arn | cut -d/ -f2)
  aws ec2 create-tags \
      --resources $instance_id \
      --tags Key=Schedule,Value=business-hours
done < recommendations.csv

If you prefer a more selective approach, review the CSV manually and tag only the instances you are comfortable stopping.

Step 4 – Deploy the AWS Instance Scheduler solution

AWS provides a Serverless Instance Scheduler CloudFormation template that creates a Lambda function, DynamoDB table, and EventBridge rules. The solution reads the Schedule tag and starts/stops instances based on a configurable schedule.

  1. Open the AWS CloudFormation console.
  2. Choose Create stackWith new resources (standard).
  3. In Specify template, paste the URL of the official template: https://aws-quickstart.s3.amazonaws.com/quickstart-aws-instance-scheduler/templates/instance-scheduler.template.yaml
  4. Provide a stack name, e.g., instance-scheduler-prod.
  5. In Parameters, set: - TagName = Schedule - TagValue = business-hours - ScheduleExpression = cron(0 18 ? * MON-FRI *) for stop at 6 PM UTC, Monday‑Friday. - StartScheduleExpression = cron(0 8 ? * MON-FRI *) for start at 8 AM UTC, Monday‑Friday.
  6. Review and create the stack.

The stack creates: - A DynamoDB table that stores schedule definitions. - A Lambda function (InstanceScheduler) that reads tags and issues StartInstances / StopInstances API calls. - Two EventBridge rules that trigger the Lambda at the start and stop times.

Note: If you need a different time zone, adjust the cron expressions accordingly. The scheduler respects daylight‑saving changes automatically when you use the cron syntax with a specific time zone.

Step 5 – Verify the automation and monitor savings

After the stack is active, test the workflow on a single instance:

INSTANCE_ID=i-0abcd1234efgh5678
aws ec2 stop-instances --instance-ids $INSTANCE_ID
aws lambda invoke --function-name InstanceScheduler --payload '{"action":"test"}' response.json
cat response.json

Check CloudWatch Logs for the Lambda function to confirm it read the tag and issued the stop command. Once verified, let the scheduler run on its schedule.

Monitoring cost impact

To see the dollar impact of stopped instances, use the Cost Explorer API with a filter for InstanceId and UsageType=BoxUsage.

aws ce get-cost-and-usage \
    --time-period Start=$(date -d '-30 days' +%Y-%m-%d),End=$(date +%Y-%m-%d) \
    --granularity DAILY \
    --filter '{"Dimensions":{"Key":"USAGE_TYPE","Values":["BoxUsage"]}}' \
    --metrics "UnblendedCost" \
    --group-by Type=DIMENSION,Key=RESOURCE_ID \
    --output table

Compare the daily cost before and after the scheduler activation. The difference is the direct savings from idle time elimination.

Step 6 – Integrate with CloudBudgetMaster’s free AWS waste finder

If you want a quick sanity check before committing to the full automation, try CloudBudgetMaster’s free AWS waste finder. It scans your account read‑only and lists idle resources with an estimated dollar impact. Use the tool to validate that the instances you tagged are indeed the biggest waste contributors.

Free AWS waste finder

Step 7 – Scale the solution across multiple accounts and regions

Large organizations often run dozens of accounts under AWS Organizations. The Instance Scheduler can be deployed once per OU (Organizational Unit) and then referenced by member accounts.

  1. In the CloudFormation stack, set DeployInAllRegions to true.
  2. Use Service Catalog to make the stack a portfolio product, allowing account owners to launch it with a single click.
  3. Store a central tag policy in AWS Organizations to enforce the Schedule tag on all new EC2 instances.
aws organizations create-policy \
    --content '{"Version":"2012-10-17","Statement":[{"Effect":"Deny","Action":"ec2:RunInstances","Condition":{"StringNotEquals":{"aws:TagKeys":"Schedule"}}}]}' \
    --description "Enforce Schedule tag on all EC2 instances" \
    --name "EnforceScheduleTag" \
    --type SERVICE_CONTROL_POLICY

Attach the policy to the root or specific OUs. This guarantees that any new instance will be eligible for automated start/stop.

Comparison of three rightsizing approaches

Approach Setup effort Ongoing maintenance Granularity Typical savings
Manual rightsizing (CLI/Console) Low – one‑time review High – requires periodic re‑evaluation Instance‑level only 5‑15 % of compute spend
Compute Optimizer only Medium – enable service + export reports Medium – need to act on recommendations manually Instance‑level + recommendation confidence 10‑20 % of compute spend
Compute Optimizer + Instance Scheduler (automated) High – CloudFormation, tagging policy, Lambda Low – automation runs daily Instance‑level + temporal (hours‑of‑day) 20‑35 % of compute spend, plus operational overhead reduction

The table shows why the combined approach is the most powerful yet often missed. It captures both under‑utilization and when the resource is needed.

Common pitfalls and how to avoid them

Pitfall Symptom Fix
Tag missing on new instances Scheduler ignores the instance, it stays running 24/7 Enforce a Service Control Policy that requires the Schedule tag on RunInstances.
Scheduler stops a critical service Unexpected downtime during off‑hours Use a whitelist tag, e.g., Schedule=never-stop, and exclude those resources in the DynamoDB schedule definition.
Compute Optimizer data lag Recommendations stale or missing Wait at least 14 days after enabling the service before pulling data.
Lambda throttling during mass start/stop Errors in CloudWatch logs, instances not started Increase Lambda concurrency limit or split the operation into batches of 50 instances.

Extending the strategy beyond EC2

The same tag‑driven scheduling concept works for other services that support start/stop APIs: - RDS – use rds:start-db-instance / rds:stop-db-instance - ElastiCacheelasticache:start-replication-group / elasticache:stop-replication-group - Redshiftredshift:resume-cluster / redshift:pause-cluster

Create separate Lambda functions or extend the existing one with additional service handlers. The core idea—identify idle resources, tag them, and let a scheduler enforce a lifecycle—remains identical.

Frequently asked questions

How often should I refresh Compute Optimizer recommendations?

Compute Optimizer updates its recommendations daily, but you only need to pull a new report once a week for most workloads. For rapidly changing environments, a nightly cron job that runs the get-recommendations CLI command ensures you never miss a new idle instance.

Does the Instance Scheduler incur additional costs?

The scheduler runs on AWS Lambda, DynamoDB, and EventBridge—all of which have generous free tiers. In a typical production environment the monthly cost is well under $5, far outweighed by the compute savings it generates.

Can I schedule resources in multiple time zones?

Yes. The CloudFormation template accepts a ScheduleExpression that can include a timezone parameter. Define separate schedule entries for each region or business unit that operates in a different time zone.

What if I need to keep an instance running for a few extra hours on a holiday?

Add a temporary tag override, e.g., Schedule=override,OverrideStart=2024-12-26T08:00:00Z,OverrideStop=2024-12-26T20:00:00Z. The Lambda function can be extended to read these override fields and adjust the start/stop times for that specific day.

Key takeaways

Create a free account to start tracking your cloud spend today.

CloudBudgetMaster automates the entire workflow for AWS today: it scans your account read‑only, surfaces idle and wasted resources, and reports the dollar impact. Support for GCP, Azure, and Snowflake is coming soon.

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