โ† AWS Compute Manager (EC2/ECS/Lambda)

Setup guide

Everything you must provision before this skill can run โ€” the exact credentials, permissions, and where to click. Links go to the official consoles and docs, which stay current.

Some setupโ‰ˆ 20-30 minaws

An AWS account with AWS CLI v2 installed and an authenticated principal (IAM Identity Center SSO profile, an assumed role, or OIDC federation in CI) that holds the EC2, Auto Scaling, ECS, Lambda, CloudWatch Logs and Compute Optimizer permissions this skill calls, plus iam:PassRole on the exact instance-profile, task and execution roles it must pass.

You need to already have

  • An AWS account, and permission to create or be assigned an IAM role (an account administrator is required if the role does not already exist)
  • AWS CLI v2.15+ installed and on PATH; v1 differs in pagination, output and the `aws logs tail` command
  • Python 3.9+ with boto3 1.34+ for the scripted paths, and `jq` for the ECS task definition rewrite
  • The instance profile, ECS task role and ECS task execution role must already exist โ€” this skill passes them, it does not create them
  • For ECS Exec: the service must be created or updated with `--enable-execute-command`, and the Session Manager plugin installed locally
  • For Compute Optimizer: the account (or the Organizations management account) must be opted in via `aws compute-optimizer update-enrollment-status --status Active`, and it needs ~12 hours of metrics before it returns recommendations

How the pieces connect

Credentials this skill needs

Set these as environment variables. Never paste secrets into a chat or commit them.

VariableWhat it isWhere to get it
AWS_PROFILE
optional
Named profile from ~/.aws/config (preferred over static keys)
format: Profile name string, e.g. `prod-compute`; the profile itself holds sso_session/sso_account_id/sso_role_name or role_arn + source_profile
Create it with `aws configure sso` (IAM Identity Center) or `aws configure --profile <name>`; it is written to ~/.aws/config. Refresh an expired SSO session with `aws sso login --profile <name>`.
AWS_REGION
Target AWS region
format: Region code such as `us-east-1`, `eu-west-1`, `ap-southeast-2` โ€” never a region name
Choose the region the workload actually runs in. Read the current default with `aws configure get region`; every command in this skill also accepts an explicit `--region`.
AWS_ACCESS_KEY_ID
secretoptional
Access key ID (only when SSO or role assumption is not available)
format: 20-character uppercase string beginning `AKIA` for a long-lived IAM user key, or `ASIA` for temporary STS credentials
AWS Console > IAM > Users > <user> > Security credentials > Access keys > Create access key. Prefer IAM Identity Center or `sts:AssumeRole` instead; long-lived user keys are the least-preferred option and cannot be retrieved after creation.
AWS_SECRET_ACCESS_KEY
secretoptional
Secret access key
format: 40-character base64-like string; shown exactly once at key creation
Displayed with the access key ID at IAM > Users > <user> > Security credentials > Create access key. If lost, delete the key and create a new one โ€” it cannot be recovered.
AWS_SESSION_TOKEN
secretoptional
Session token (required whenever the key ID starts with ASIA)
format: Long opaque string, several hundred characters
Returned alongside temporary credentials by `aws sts assume-role --role-arn <arn> --role-session-name compute-mgr` or by IAM Identity Center. Expires with the session (15 min to 12 h).
AWS_ROLE_ARN
optional
Role to assume in CI via OIDC web identity federation
format: arn:aws:iam::<account-id>:role/<role-name>
IAM > Roles > Create role > Web identity, with the CI provider's OIDC endpoint as the identity provider. Used together with AWS_WEB_IDENTITY_TOKEN_FILE; this removes stored long-lived keys entirely.
AWS_ALLOWED_ACCOUNT_IDS
Skill-local guard: account IDs this run may mutate (not an AWS-native variable)
format: Space- or comma-separated list of 12-digit account IDs, e.g. `111122223333 444455556666`
Set by you, not by AWS. Populate it with the account IDs you intend to change; the skill refuses to run any mutating command when the value from `aws sts get-caller-identity --query Account` is not in the list, and refuses outright when it is unset.

Permissions to grant

arn:aws:iam::aws:policy/ReadOnlyAccessIAM policy

Simplest way to enable the whole read/inventory half of the skill: describing instances, AMIs, launch templates, ASGs, ECS services and task definitions, Lambda configuration and aliases, log groups and CloudWatch metrics.

โ†ณ Prefer composing the narrower AWS managed read policies instead: AmazonEC2ReadOnlyAccess, AmazonECS_FullAccess is NOT read-only so use a custom ecs:Describe*/ecs:List* policy, AWSLambda_ReadOnlyAccess, CloudWatchLogsReadOnlyAccess and ComputeOptimizerReadOnlyAccess.

ec2:DescribeInstancesIAM policy

Inventory instances, resolve Name tags, read instance type/state/AMI/AZ, and print the blast radius before any destructive call.

โ†ณ Describe actions do not support resource-level permissions; scope with the ec2:Region condition key and, where supported, aws:ResourceTag on the mutating actions instead.

ec2:RunInstancesIAM policy

Launch EC2 instances from a resolved AMI with IMDSv2 required and encrypted gp3 root volumes.

โ†ณ Condition on ec2:InstanceType, ec2:Subnet and aws:RequestTag/Environment, and require ec2:MetadataHttpTokens = required so IMDSv1 instances cannot be launched at all.

ec2:TerminateInstancesIAM policy

Decommission instances after an explicit, resource-naming confirmation; always exercised with DryRun first.

โ†ณ Restrict to instances carrying a specific tag using a Condition on aws:ResourceTag/Environment, and exclude production entirely from the automation principal.

ec2:CreateImageIAM policy

Bake tagged AMIs from a running instance before an ASG roll, so a rollback image always exists.

โ†ณ Pair with ec2:CreateTags restricted via aws:RequestTag, and keep ec2:DeregisterImage on a separate, more tightly held policy.

autoscaling:StartInstanceRefreshIAM policy

Roll a new launch template version through an Auto Scaling group with MinHealthyPercentage and AutoRollback set.

โ†ณ Scope the Resource element to the specific ASG ARNs, and grant autoscaling:RollbackInstanceRefresh alongside it so a bad roll can always be reverted.

ecs:UpdateServiceIAM policy

Point a service at a new task definition revision, force a new deployment, and roll back to the previously recorded revision.

โ†ณ Scope Resource to arn:aws:ecs:<region>:<account>:service/<cluster>/<service> and add a Condition on ecs:cluster so a single cluster is reachable.

ecs:RegisterTaskDefinitionIAM policy

Register a new revision with only the container image changed, keeping every other field identical to the running revision.

โ†ณ RegisterTaskDefinition does not support resource-level permissions, so pair it with a tightly scoped iam:PassRole and rely on ecs:UpdateService scoping to bound the impact.

iam:PassRoleIAM policy

Required to attach an instance profile in RunInstances and task/execution roles in RegisterTaskDefinition; without it both calls fail with AccessDeniedException.

โ†ณ Always enumerate the exact role ARNs in Resource and add Condition {"StringEquals": {"iam:PassedToService": ["ec2.amazonaws.com", "ecs-tasks.amazonaws.com"]}}. A wildcard PassRole is a privilege-escalation path to any role in the account.

lambda:UpdateFunctionCodeIAM policy

Ship a new deployment package and publish it as an immutable numbered version.

โ†ณ Scope Resource to arn:aws:lambda:<region>:<account>:function:<name>; grant lambda:PublishVersion on the same resource so every deploy is versioned.

lambda:UpdateAliasIAM policy

Shift traffic with AdditionalVersionWeights for a canary, promote to 100%, and roll back instantly by restoring the previous version.

โ†ณ Scope Resource to the alias ARN (arn:aws:lambda:<region>:<account>:function:<name>:live) rather than the function, so only the intended alias can be repointed.

arn:aws:iam::aws:policy/CloudWatchLogsReadOnlyAccessIAM policy

Tail and query ECS and Lambda log groups and run CloudWatch Logs Insights queries to verify a deploy actually works.

โ†ณ Replace with an inline policy granting logs:FilterLogEvents, logs:GetLogEvents, logs:StartQuery and logs:GetQueryResults on arn:aws:logs:<region>:<account>:log-group:/aws/lambda/<name>:* and /ecs/<service>:*.

arn:aws:iam::aws:policy/ComputeOptimizerReadOnlyAccessIAM policy

Fetch EC2, Lambda and ECS-on-Fargate right-sizing recommendations to back a resize proposal with data rather than intuition.

โ†ณ Grant only the three GetEC2InstanceRecommendations / GetLambdaFunctionRecommendations / GetECSServiceRecommendations actions if the account also uses other Compute Optimizer surfaces.

arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCoreIAM policy

Attached to the EC2 instance role (not the operator) so Session Manager can replace SSH for debugging without opening port 22.

โ†ณ This goes on the instance profile. The operator separately needs ssm:StartSession scoped to instances carrying a specific tag.

Step by step

  1. 1

    Install AWS CLI v2 and verify the version

    Install from the official installer, then run `aws --version` and confirm it prints `aws-cli/2.x`. If it prints `aws-cli/1.x`, remove the v1 install or fix PATH โ€” `aws logs tail`, `--cli-input-json` behaviour and pagination all differ. Also install `jq` and the Session Manager plugin.

    Open in the console / docs โ†—
  2. 2

    Authenticate with IAM Identity Center rather than long-lived keys

    Run `aws configure sso`, supply the SSO start URL and region, pick the account and permission set, and name the profile (for example `prod-compute`). Then `export AWS_PROFILE=prod-compute` and `aws sso login --profile prod-compute`. Sessions expire; re-run `aws sso login` when you hit ExpiredToken.

    Open in the console / docs โ†—
  3. 3

    Or assume a dedicated compute-operations role

    Create the role with a trust policy naming your principal, then either add `role_arn` + `source_profile` to ~/.aws/config, or run `aws sts assume-role --role-arn arn:aws:iam::<account>:role/compute-ops --role-session-name compute-mgr` and export AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN from the response.

    Open in the console / docs โ†—
  4. 4

    Attach the permission set this skill needs

    Start from ReadOnlyAccess plus a customer-managed policy granting the ec2:*, autoscaling:*, ecs:* and lambda:* actions listed in the skill's Required access table. Add iam:PassRole restricted to the exact instance-profile, task and execution role ARNs with a Condition on iam:PassedToService.

    Open in the console / docs โ†—
  5. 5

    Set the region and the account allow-list

    `export AWS_REGION=us-east-1` and `export AWS_ALLOWED_ACCOUNT_IDS="111122223333"`. The second is a skill-local guard, not an AWS variable: every mutating path compares `aws sts get-caller-identity --query Account --output text` against it and aborts on a mismatch or when it is unset.

    Open in the console / docs โ†—
  6. 6

    Enable ECS Exec on services you will need to debug

    Run `aws ecs update-service --cluster <cluster> --service <service> --enable-execute-command --force-new-deployment`, ensure the task role grants ssmmessages:CreateControlChannel, ssmmessages:CreateDataChannel, ssmmessages:OpenControlChannel and ssmmessages:OpenDataChannel, then verify with `aws ecs describe-tasks --cluster <cluster> --tasks <id> --query 'tasks[0].enableExecuteCommand'`.

    Open in the console / docs โ†—
  7. 7

    Opt in to Compute Optimizer for right-sizing

    Run `aws compute-optimizer update-enrollment-status --status Active`. Recommendations require roughly 12 hours of CloudWatch metrics and 30 hours of uptime before they appear; until then fall back to `aws cloudwatch get-metric-data` over a 14-day window.

    Open in the console / docs โ†—
  8. 8

    Dry-run before trusting the setup

    Confirm the safety rail works end to end: `aws ec2 terminate-instances --instance-ids i-0123456789abcdef0 --dry-run` must return `An error occurred (DryRunOperation)` if you hold the permission, or `UnauthorizedOperation` if you do not. Never proceed to a real mutating call until you have seen DryRunOperation.

    Open in the console / docs โ†—

Check it worked

aws sts get-caller-identity --output table && aws ec2 describe-instances --max-items 1 --query 'Reservations[].Instances[].InstanceId' --output text && aws ecs list-clusters --query 'clusterArns[:3]' --output text && aws lambda list-functions --max-items 1 --query 'Functions[].FunctionName' --output text

If you hit an error

An error occurred (DryRunOperation) when calling the TerminateInstances operation: Request would have succeeded, but DryRun flag is set.

Cause: Not a failure. This is the success signal for a `--dry-run` call: the parameters are valid and the principal is authorised.

Fix: Treat it as the green light. Re-run the identical command without `--dry-run` only after explicit confirmation naming the instance IDs and the account.

An error occurred (UnauthorizedOperation) when calling the RunInstances operation: You are not authorized to perform this operation.

Cause: The principal lacks ec2:RunInstances, or a Condition (tag, instance type, subnet, region) or an SCP denies it. EC2 deliberately does not say which.

Fix: Re-run with `--dry-run` and decode the message: `aws sts decode-authorization-message --encoded-message <blob>` (needs sts:DecodeAuthorizationMessage). Then confirm with `aws iam simulate-principal-policy --action-names ec2:RunInstances`.

An error occurred (AccessDenied) when calling the RegisterTaskDefinition operation: User: arn:aws:iam::111122223333:role/deployer is not authorized to perform: iam:PassRole on resource: arn:aws:iam::111122223333:role/ecsTaskExecutionRole

Cause: The task definition names an execution or task role that the deploying principal is not allowed to pass.

Fix: Add iam:PassRole to the deployer policy with Resource set to that exact role ARN and Condition {"StringEquals": {"iam:PassedToService": "ecs-tasks.amazonaws.com"}}.

An error occurred (ExpiredTokenException) when calling the DescribeServices operation: The security token included in the request is expired

Cause: Temporary STS or IAM Identity Center credentials aged out mid-session; typical for 1-hour assumed roles and SSO sessions.

Fix: Re-run `aws sso login --profile <name>`, or re-issue `aws sts assume-role` and re-export AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN. For long deploys, prefer a profile with role_arn so the CLI refreshes automatically.

An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid.

Cause: The access key was deleted or deactivated, AWS_SESSION_TOKEN is missing for an ASIA-prefixed temporary key, or the credentials belong to a different partition (GovCloud/China).

Fix: Check `aws configure list` for where each value is resolved from. If the key ID starts with ASIA you must also export AWS_SESSION_TOKEN; if it starts with AKIA, confirm the key is still Active in IAM.

An error occurred (ClientException) when calling the RegisterTaskDefinition operation: Fargate requires task definition to have execution role ARN to support ECR images.

Cause: executionRoleArn was dropped from the task definition JSON โ€” usually by rebuilding it by hand instead of round-tripping describe-task-definition.

Fix: Regenerate the JSON from `aws ecs describe-task-definition --query taskDefinition`, delete only the read-only fields, and change only the image. Never author the blob from scratch.

Waiter ServicesStable failed: Max attempts exceeded

Cause: Tasks are failing to reach a steady state โ€” image pull failure, failing container health check, target group health check failing, or no capacity to place a replacement task.

Fix: Read `aws ecs describe-services --query 'services[0].events[:10].message'` and `aws ecs describe-tasks --query 'tasks[].stoppedReason'`. Check maximumPercent gives placement headroom, then roll back to the recorded previous task definition.

An error occurred (ResourceConflictException) when calling the UpdateFunctionCode operation: The operation cannot be performed at this time. An update is in progress for resource: arn:aws:lambda:us-east-1:111122223333:function:my-fn

Cause: A previous update-function-code or update-function-configuration has not finished; Lambda serialises updates per function.

Fix: Wait for the function to settle with `aws lambda wait function-updated-v2 --function-name my-fn` (or poll LastUpdateStatus until Successful) before issuing the next call. Never retry in a tight loop.

An error occurred (InstanceRefreshInProgress) when calling the StartInstanceRefresh operation: An Instance Refresh is already in progress and blocks the execution of this Instance Refresh.

Cause: An earlier refresh on the same Auto Scaling group is still running or was never cancelled.

Fix: Inspect it with `aws autoscaling describe-instance-refreshes --auto-scaling-group-name <asg>`; wait for Successful, or stop it with `aws autoscaling cancel-instance-refresh --auto-scaling-group-name <asg>` before starting a new one.

An error occurred (VcpuLimitExceeded) when calling the RunInstances operation: You have requested more vCPU capacity than your current vCPU limit of 32 allows for the instance bucket that the specified instance type belongs to.

Cause: The per-family On-Demand vCPU service quota for the region is exhausted.

Fix: Check the quota with `aws service-quotas get-service-quota --service-code ec2 --quota-code L-1216C47A`, request an increase, pick a smaller instance type, or launch into a different region or family.

An error occurred (InsufficientInstanceCapacity) when calling the RunInstances operation: We currently do not have sufficient capacity in the Availability Zone you requested.

Cause: AWS has no free capacity for that instance type in that AZ right now. It is a capacity condition, not a permission or quota problem.

Fix: Retry in another AZ or subnet, choose a different instance type or size, or use an ASG with multiple instance types and subnets so it can place elsewhere automatically.

Unable to locate credentials. You can configure credentials by running "aws configure".

Cause: No profile, environment variables, or instance/container role was resolvable โ€” often AWS_PROFILE points at a profile that does not exist, or the shell lost the exported variables.

Fix: Run `aws configure list` to see which source each value comes from, confirm ~/.aws/config contains the profile, and re-export AWS_PROFILE or the key variables. In CI, confirm the OIDC role assumption step actually ran.

Official documentation: https://docs.aws.amazon.com/cli/latest/reference/ โ†—

API operations this skill uses (20)

Every call the skill makes, linked to its official reference page.

OperationCallPermissionRef
Verify caller account and identity
Mandatory first call before any mutation: proves which account and principal the credentials resolve to, so the account allow-list check can pass or abort.
CLI aws sts get-caller-identity --query '{Account:Account,Arn:Arn}' --output tablests:GetCallerIdentitydocs โ†—
Describe EC2 instances
Inventory and blast-radius enumeration: resolves instance IDs, types, state, AMI and AZ before any change, and prints exactly what a destructive action would hit.
CLI aws ec2 describe-instances --filters "Name=tag:Environment,Values=prod" "Name=instance-state-name,Values=running" --query 'Reservations[].Instances[].{Id:InstanceId,Type:InstanceType,AMI:ImageId,AZ:Placement.AvailabilityZone}'ec2:DescribeInstancesdocs โ†—
Launch an EC2 instance (dry-run first)
Provisions instances with IMDSv2 required and encrypted gp3 roots; the dry-run pass validates permissions and parameters before anything is billed.
CLI aws ec2 run-instances --dry-run --image-id <ami> --instance-type t3.small --subnet-id <subnet> --iam-instance-profile Name=<profile> --metadata-options HttpTokens=required --block-device-mappings 'DeviceName=/dev/xvda,Ebs={VolumeSize=30,VolumeType=gp3,Encrypted=true}'ec2:RunInstances (plus iam:PassRole for the instance profile)docs โ†—
Terminate EC2 instances
Decommissions instances. Always dry-run first and always gate the real call behind explicit confirmation that names the instance IDs and account.
CLI aws ec2 terminate-instances --instance-ids <ids> --dry-run # then re-run without --dry-run only after confirmationec2:TerminateInstancesdocs โ†—
Create a tagged AMI from a running instance
Bakes a rollback image before an ASG roll. `--no-reboot` produces a crash-consistent snapshot, so it must not be used on databases.
CLI aws ec2 create-image --instance-id <id> --name "<app>-$(date -u +%Y%m%dT%H%M%SZ)" --no-reboot --tag-specifications "ResourceType=image,Tags=[{Key=App,Value=<app>}]"ec2:CreateImage (plus ec2:CreateTags)docs โ†—
Create a launch template version pinning a new AMI
Immutably records the new AMI as a version, which is what makes an ASG rollback possible โ€” the previous version stays addressable.
CLI aws ec2 create-launch-template-version --launch-template-id <lt> --source-version '$Latest' --launch-template-data '{"ImageId":"<ami>"}'ec2:CreateLaunchTemplateVersiondocs โ†—
Point an Auto Scaling group at a launch template version
Changes which template new instances launch from, and adjusts capacity. Scaling to zero is destructive and requires confirmation.
CLI aws autoscaling update-auto-scaling-group --auto-scaling-group-name <asg> --launch-template LaunchTemplateId=<lt>,Version=<n> --min-size 2 --max-size 6 --desired-capacity 3autoscaling:UpdateAutoScalingGroupdocs โ†—
Start an instance refresh with auto-rollback
Rolls the new AMI through the ASG while keeping 90% healthy, and reverts automatically if the replacements fail health checks.
CLI aws autoscaling start-instance-refresh --auto-scaling-group-name <asg> --preferences '{"MinHealthyPercentage":90,"InstanceWarmup":300,"AutoRollback":true}'autoscaling:StartInstanceRefreshdocs โ†—
Track or roll back an instance refresh
Monitors rollout progress and reverts already-replaced instances to the prior launch template version when the new build misbehaves.
CLI aws autoscaling describe-instance-refreshes --auto-scaling-group-name <asg> --query 'InstanceRefreshes[0].{Status:Status,Pct:PercentageComplete,Reason:StatusReason}' | aws autoscaling rollback-instance-refresh --auto-scaling-group-name <asg>autoscaling:DescribeInstanceRefreshes, autoscaling:RollbackInstanceRefreshdocs โ†—
Describe an ECS service and capture the rollback revision
Records the currently deployed task definition ARN as the rollback target and exposes rolloutState plus service events for diagnosing a stalled deploy.
CLI aws ecs describe-services --cluster <cluster> --services <service> --query 'services[0].{TD:taskDefinition,Desired:desiredCount,Running:runningCount,Rollout:deployments[].rolloutState}'ecs:DescribeServicesdocs โ†—
Fetch the live task definition for a safe image swap
Round-tripping the running definition is the only safe way to change just the image; hand-authored JSON drops executionRoleArn, logConfiguration and secrets.
CLI aws ecs describe-task-definition --task-definition <family:rev> --query taskDefinitionecs:DescribeTaskDefinitiondocs โ†—
Register a new task definition revision
Creates the immutable revision the deploy will point at. Read-only fields (taskDefinitionArn, revision, status, requiresAttributes, compatibilities, registeredAt/By) must be stripped first.
CLI aws ecs register-task-definition --cli-input-json file:///tmp/td.jsonecs:RegisterTaskDefinition (plus iam:PassRole for task and execution roles)docs โ†—
Deploy or roll back an ECS service
Single command for both directions: forward to the new revision with the circuit breaker armed, or back to the recorded previous ARN to roll back.
CLI aws ecs update-service --cluster <cluster> --service <service> --task-definition <arn> --force-new-deployment --deployment-configuration 'deploymentCircuitBreaker={enable=true,rollback=true},maximumPercent=200,minimumHealthyPercent=100'ecs:UpdateServicedocs โ†—
Exec into a running ECS task
Debug a live container without SSH or a bastion; requires enableExecuteCommand on the service and ssmmessages permissions on the task role.
CLI aws ecs execute-command --cluster <cluster> --task <task-id> --container <name> --interactive --command "/bin/sh"ecs:ExecuteCommanddocs โ†—
Publish new Lambda code as an immutable version
Ships the package and produces a numbered version, which is what makes an instant alias rollback possible.
CLI aws lambda update-function-code --function-name <fn> --s3-bucket <b> --s3-key <k> --publishlambda:UpdateFunctionCode, lambda:PublishVersiondocs โ†—
Shift, promote or roll back a Lambda alias
Runs a weighted canary with the previous version still primary, then promotes with --routing-config '{}', or rolls back instantly by restoring the previous version.
CLI aws lambda update-alias --function-name <fn> --name live --function-version <prev> --routing-config 'AdditionalVersionWeights={"<new>"=0.1}'lambda:UpdateAliasdocs โ†—
Tune Lambda memory and timeout
Applies a right-sizing decision. Memory also scales CPU, so a larger value can be cheaper per invocation; always follow with function-updated-v2 before the next call.
CLI aws lambda update-function-configuration --function-name <fn> --memory-size 512 --timeout 30lambda:UpdateFunctionConfigurationdocs โ†—
Tail ECS or Lambda logs
Confirms a deploy actually works at runtime rather than only that the API returned success, and surfaces crash loops health checks would miss.
CLI aws logs tail /aws/lambda/<fn> --since 15m --format short --filter-pattern '?ERROR ?Exception'logs:FilterLogEvents, logs:DescribeLogGroupsdocs โ†—
Query utilisation metrics for right-sizing
Pulls 14 days of CPUUtilization, MemoryUtilization or Duration so a resize proposal is backed by p95 data rather than a guess.
CLI aws cloudwatch get-metric-data --start-time 2026-07-14T00:00:00Z --end-time 2026-07-28T00:00:00Z --metric-data-queries file://queries.jsoncloudwatch:GetMetricDatadocs โ†—
Fetch Compute Optimizer EC2 recommendations
Cross-checks the CloudWatch analysis with AWS's own OVER_PROVISIONED / UNDER_PROVISIONED finding before proposing an instance type change.
CLI aws compute-optimizer get-ec2-instance-recommendations --query 'instanceRecommendations[].{Id:instanceArn,Current:currentInstanceType,Finding:finding,Best:recommendationOptions[0].instanceType}'compute-optimizer:GetEC2InstanceRecommendationsdocs โ†—