110+ AWS CLI commands for S3, EC2, IAM, Lambda, CloudWatch, SSM and more. Searchable, filterable, copy with one click. Includes the Credential Chain Debugger.
Everything runs in your browser. No commands or data are sent to any server.
5 essential commands to get you started. The full reference is right below.
aws configure First command to run on a new machine to set up your access key, secret key, default region, and output format.
aws sts get-caller-identity The single most important debugging command in the entire AWS CLI, run this whenever something is failing with auth or permission errors.
aws s3 ls List all buckets or list objects inside a bucket.
aws ec2 describe-instances --query "Reservations[].Instances[].{ID:InstanceId,State:State.Name,Type:InstanceType}" --output table List all EC2 instances and their current state in your account and region.
aws s3 cp ./file.txt s3://my-bucket/folder/file.txt Upload a single local file to a specific key in an S3 bucket.
aws configure ↓ Click command to explain
When to use this
First command to run on a new machine to set up your access key, secret key, default region, and output format.
Gotcha
This stores credentials in plaintext at ~/.aws/credentials, never commit that file to git.
aws configure --profile myprofile ↓ Click command to explain
When to use this
Set up a named profile for a second AWS account without overwriting your default.
Gotcha
The profile name you use here must be used exactly with --profile on every command or with export AWS_PROFILE.
aws configure list ↓ Click command to explain
When to use this
Debug which credentials and region are actually active right now. The source column shows whether each value comes from an env variable, config file, or default.
aws configure list-profiles ↓ Click command to explain
When to use this
See all named profiles before switching or to debug a profile-not-found error.
aws sts get-caller-identity ↓ Click command to explain
When to use this
Verify which AWS account and IAM identity is active before running any destructive command.
Gotcha
This is the first command to run when anything fails with an authentication error. It shows exactly who AWS thinks you are.
aws configure sso ↓ Click command to explain
When to use this
Set up AWS SSO so you can log in with your browser instead of long-lived access keys.
Gotcha
After setup you still need to run aws sso login --profile yourprofile before each session or commands fail with confusing token expired errors.
aws sso login --profile myprofile ↓ Click command to explain
When to use this
Refresh your SSO session when it has expired so subsequent commands work again.
export AWS_PROFILE=myprofile ↓ Click command to explain
When to use this
Switch the active profile for your entire shell session without adding --profile to every command.
Gotcha
This environment variable persists for the entire terminal session including any scripts you run from it, unset it with unset AWS_PROFILE when done.
aws configure set cli_pager "" ↓ Click command to explain
When to use this
Disable the default pager that pipes all CLI v2 output through less, which causes CI scripts to hang waiting for a keypress.
Gotcha
This is the single most common reason AWS CLI v2 scripts hang silently in CI pipelines, set it globally or pass --no-cli-pager on every command.
aws sts get-caller-identity --query Account --output text ↓ Click command to explain
--query JMESPath expression selecting which part of the JSON response to return --output text Print the result as a bare string instead of JSON, ideal for shell variables When to use this
Extract a single value from any AWS CLI response as a bare string for use in shell scripts and variables.
Gotcha
If your --query expression returns null it means the path is wrong, AWS CLI does not error on a bad JMESPath expression, it silently returns null.
aws configure get region ↓ Click command to explain
When to use this
Check a single configuration value like region or output format for the active profile from within a script.
aws --version ↓ Click command to explain
When to use this
Confirm whether you are running AWS CLI v1 or v2 before following a tutorial, since many flags and behaviors differ between major versions.
aws s3 ls ↓ Click command to explain
When to use this
List all buckets or list objects inside a bucket.
Gotcha
aws s3 ls with no arguments lists all buckets, aws s3 ls s3://bucketname/ lists objects, the trailing slash matters for listing a prefix correctly.
aws s3 ls s3://my-bucket/prefix/ --recursive ↓ Click command to explain
--recursive List all objects under the prefix, not just the top level --human-readable Show sizes in KB, MB, GB instead of raw bytes When to use this
List every object under a folder-like prefix in a bucket, not just the immediate children.
aws s3 cp ./file.txt s3://my-bucket/folder/file.txt ↓ Click command to explain
When to use this
Upload a single local file to a specific key in an S3 bucket.
Gotcha
s3://bucket/path and s3://bucket/path/ are different, adding a trailing slash means copy into that prefix as a folder not replace that exact key.
aws s3 cp s3://my-bucket/folder/file.txt ./file.txt ↓ Click command to explain
--recursive Download an entire prefix instead of a single object When to use this
Download a single object from S3 to the local filesystem.
aws s3 sync ./local-folder s3://my-bucket/prefix/ ↓ Click command to explain
--delete Remove destination files that no longer exist in the source --dryrun Preview exactly what would change without executing anything --exclude / --include Filter which files are synced by glob pattern When to use this
Upload only new or changed files from a local folder to a bucket, useful for deploying static sites.
Gotcha
Always run with --dryrun before the first time you use --delete on a production bucket, sync with --delete permanently removes files with no undo.
aws s3 sync s3://my-bucket/prefix/ ./local-folder ↓ Click command to explain
When to use this
Pull down only new or changed objects from a bucket to a local folder, such as restoring a backup.
aws s3 rm s3://my-bucket/folder/ --recursive ↓ Click command to explain
--recursive Delete every object under the prefix instead of a single object --dryrun Preview which objects would be deleted without deleting them When to use this
Remove an object or an entire folder-like prefix of objects from a bucket.
Gotcha
There is no trash or undo in S3, deleted objects are gone, always use --dryrun first and double check the prefix before running without it.
aws s3 mb s3://my-new-bucket --region us-east-1 ↓ Click command to explain
When to use this
Create a brand-new S3 bucket in a specific region.
Gotcha
Bucket names are globally unique across all AWS accounts, if the name is taken you get an error with no suggestion.
aws s3 rb s3://my-bucket --force ↓ Click command to explain
--force Delete all objects in the bucket first, then delete the bucket itself When to use this
Permanently remove an empty or non-empty bucket, such as tearing down a temporary environment.
Gotcha
This fails on a versioned bucket even with --force since old versions remain, you must delete all object versions first with list-object-versions and delete-objects.
aws s3 presign s3://my-bucket/file.txt --expires-in 3600 ↓ Click command to explain
When to use this
Generate a temporary public URL to share a private S3 object without changing bucket permissions.
Gotcha
The URL is valid for anyone who has it until it expires, it uses your current credentials so if those expire before the URL does the URL stops working.
aws s3api head-object --bucket my-bucket --key folder/file.txt ↓ Click command to explain
When to use this
Check if an object exists and see its metadata without downloading it.
Gotcha
Returns a 404 error if the object does not exist which is a useful existence check in scripts.
aws s3api list-object-versions --bucket my-bucket ↓ Click command to explain
When to use this
See all versions of all objects in a versioned bucket, required before you can fully delete a versioned bucket.
Gotcha
aws s3 rb --force does not work on versioned buckets, you must delete all versions first using list-object-versions and delete-objects in a loop.
aws s3api get-bucket-policy --bucket my-bucket ↓ Click command to explain
When to use this
Inspect the JSON resource policy attached to a bucket to audit who can access it.
aws s3api put-object-acl --bucket my-bucket --key file.txt --acl public-read ↓ Click command to explain
When to use this
Make a specific object publicly readable via a canned ACL rather than a bucket-wide policy.
Gotcha
Bucket-level Block Public Access settings override object ACLs, if Block Public Access is enabled making an object public-read via ACL silently fails to make it public.
aws s3api list-objects-v2 --bucket my-bucket --no-paginate ↓ Click command to explain
--no-paginate Disable the CLI's automatic looping through every page of results When to use this
Get one raw page of API results without the CLI looping through all pages automatically.
Gotcha
Combining --page-size and --max-items with different values can cause missing or duplicated items, if you use both keep them equal.
aws s3api list-objects-v2 --bucket my-bucket --max-items 100 ↓ Click command to explain
--max-items Return at most this many results, along with a NextToken if more exist --starting-token Resume a previous paginated call using the NextToken it returned When to use this
Get only the first 100 results and use the returned NextToken with --starting-token to resume pagination in the next call.
aws ec2 describe-instances --query "Reservations[].Instances[].{ID:InstanceId,State:State.Name,Type:InstanceType}" --output table ↓ Click command to explain
--query Reservations[].Instances[].{...} Project a readable summary instead of the raw nested JSON --filters Name=instance-state-name,Values=running Show only instances in a specific state When to use this
List all EC2 instances and their current state in your account and region.
Gotcha
The raw output is deeply nested JSON that is almost unreadable without a --query expression, always add --query and --output table when reading interactively.
aws ec2 describe-instances --filters Name=instance-state-name,Values=running --query "Reservations[].Instances[].[InstanceId,InstanceType,PublicIpAddress]" --output table ↓ Click command to explain
When to use this
Get a quick table of instance ID, type, and public IP for every currently running instance.
aws ec2 start-instances --instance-ids i-1234567890abcdef0 ↓ Click command to explain
When to use this
Power on an instance that was previously stopped.
aws ec2 stop-instances --instance-ids i-1234567890abcdef0 ↓ Click command to explain
When to use this
Shut down an instance to stop paying for compute while keeping its EBS volumes and configuration.
Gotcha
Stopping an instance does not delete it or its EBS volumes, you continue to pay for EBS storage while stopped.
aws ec2 terminate-instances --instance-ids i-1234567890abcdef0 ↓ Click command to explain
When to use this
Permanently destroy an instance that is no longer needed.
Gotcha
This permanently deletes the instance and by default also deletes any EBS root volumes with the DeleteOnTermination flag set, there is no undo and no confirmation prompt.
aws ec2 run-instances --image-id ami-12345678 --instance-type t3.micro --key-name my-keypair --security-group-ids sg-12345678 --subnet-id subnet-12345678 --count 1 ↓ Click command to explain
When to use this
Launch one or more new EC2 instances from an AMI with a specific instance type, key pair, and network configuration.
Gotcha
You will be billed immediately once the instance enters the running state.
aws ec2 describe-images --owners self --query "Images[*].{ID:ImageId,Name:Name}" --output table ↓ Click command to explain
--owners self Only show AMIs owned by your account instead of all public AMIs When to use this
List AMIs you own in the current region.
Gotcha
Without --owners self this queries public AMIs which returns thousands of results and is very slow.
aws ec2 create-tags --resources i-1234567890abcdef0 --tags Key=Name,Value=my-server ↓ Click command to explain
When to use this
Add a Name tag or any custom tag to an instance, volume, or other taggable EC2 resource.
aws ec2 describe-security-groups --group-ids sg-12345678 ↓ Click command to explain
When to use this
Inspect the inbound and outbound rules of a specific security group.
aws ec2 authorize-security-group-ingress --group-id sg-12345678 --protocol tcp --port 22 --cidr 0.0.0.0/0 ↓ Click command to explain
When to use this
Allow inbound traffic on a specific port and protocol, such as opening SSH access to an instance.
Gotcha
0.0.0.0/0 opens the port to the entire internet, always restrict to your IP or a specific CIDR in production.
aws ec2 describe-key-pairs ↓ Click command to explain
When to use this
See which SSH key pairs are registered in the current region.
aws ec2 create-key-pair --key-name my-keypair --query KeyMaterial --output text > my-keypair.pem && chmod 400 my-keypair.pem ↓ Click command to explain
When to use this
Generate a brand-new key pair for SSH access to future EC2 instances.
Gotcha
AWS only shows you the private key material once at creation time, if you lose this file you cannot recover the key and must create a new one.
aws ec2 describe-volumes --filters Name=status,Values=available ↓ Click command to explain
When to use this
Find detached EBS volumes you are paying for but not using.
aws ec2 describe-snapshots --owner-ids self ↓ Click command to explain
When to use this
Review existing EBS snapshots for backup auditing or cost review.
aws ec2 describe-instances --query "Reservations[].Instances[?State.Name=='running'].[InstanceId,Tags[?Key=='Name'].Value|[0]]" --output text ↓ Click command to explain
When to use this
Filter EC2 instances by state and extract specific fields in one query.
Gotcha
If any part of your JMESPath expression has a typo AWS returns null with no error message, test your query incrementally adding one part at a time.
aws iam list-users --query "Users[*].{User:UserName,Created:CreateDate}" --output table ↓ Click command to explain
When to use this
See every IAM user in the account along with when each one was created.
aws iam create-user --user-name newuser ↓ Click command to explain
When to use this
Create a new IAM identity for a person or service that needs AWS access.
Gotcha
Creating a user does not give them any permissions or a way to log in, you must also create access keys or a login profile and attach policies separately.
aws iam create-access-key --user-name myuser ↓ Click command to explain
When to use this
Generate programmatic access credentials for an IAM user.
Gotcha
The secret access key is only shown once at creation time, save it immediately, you cannot retrieve it again and must create a new key pair if lost.
aws iam attach-user-policy --user-name myuser --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess ↓ Click command to explain
When to use this
Grant an IAM user permissions by attaching an AWS managed or customer managed policy.
Gotcha
Attaching AdministratorAccess to a user instead of scoping to minimum required permissions is the most common IAM security mistake.
aws iam list-attached-user-policies --user-name myuser ↓ Click command to explain
When to use this
Audit exactly which managed policies are attached to a specific user.
aws iam create-role --role-name my-role --assume-role-policy-document file://trust-policy.json ↓ Click command to explain
When to use this
Create a role that a service or another account can assume, defined by a trust policy document.
Gotcha
The trust policy controls who can assume the role, confusing trust policy with permissions policy is the most common IAM conceptual error.
aws iam attach-role-policy --role-name my-role --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess ↓ Click command to explain
When to use this
Grant a role the permissions it needs by attaching a managed policy.
aws iam create-policy --policy-name my-policy --policy-document file://policy.json ↓ Click command to explain
When to use this
Define a reusable custom permissions policy from a local JSON document.
aws iam simulate-principal-policy --policy-source-arn arn:aws:iam::123456789012:user/myuser --action-names s3:GetObject --resource-arns arn:aws:s3:::my-bucket/* ↓ Click command to explain
When to use this
Test whether an IAM identity has permission to perform an action before deploying code that needs it.
Gotcha
Most developers do not know this command exists and instead find out about missing permissions by running the actual operation and getting a 403.
aws iam list-roles --query "Roles[*].{Name:RoleName,ARN:Arn}" --output table ↓ Click command to explain
When to use this
See every IAM role in the account and its ARN.
aws iam get-role --role-name my-role ↓ Click command to explain
When to use this
Inspect a role's trust policy and metadata.
aws iam delete-access-key --user-name myuser --access-key-id AKIAIOSFODNN7EXAMPLE ↓ Click command to explain
When to use this
Revoke a specific access key, such as one that leaked or is being rotated out.
aws sts get-caller-identity ↓ Click command to explain
When to use this
The single most important debugging command in the entire AWS CLI, run this whenever something is failing with auth or permission errors.
aws sts assume-role --role-arn arn:aws:iam::123456789012:role/my-role --role-session-name my-session ↓ Click command to explain
--role-session-name Required in practice, as a name identifying this temporary session in logs and CloudTrail --duration-seconds Extend the session length beyond the default 1 hour, up to the role's configured maximum When to use this
Obtain temporary credentials for a role, such as a cross-account role, for the current session.
Gotcha
The --role-session-name parameter is required in practice even though it looks optional, default session duration is 1 hour which may be too short for long-running scripts, use --duration-seconds to extend up to the role's maximum.
creds=$(aws sts assume-role --role-arn arn:aws:iam::123456789012:role/my-role --role-session-name my-session --query Credentials --output json) && export AWS_ACCESS_KEY_ID=$(echo $creds | jq -r .AccessKeyId) && export AWS_SECRET_ACCESS_KEY=$(echo $creds | jq -r .SecretAccessKey) && export AWS_SESSION_TOKEN=$(echo $creds | jq -r .SessionToken) ↓ Click command to explain
When to use this
Assume a role and automatically export the temporary credentials into your shell environment for immediate use.
Gotcha
These environment variables override everything else in the credential chain, unset all three when done or your next command will use these temporary credentials even after they expire.
# ~/.aws/config
[profile cross-account]
role_arn = arn:aws:iam::123456789012:role/my-role
source_profile = default ↓ Click command to explain
When to use this
The correct long-term way to work with assumed roles, AWS CLI automatically calls sts assume-role and refreshes credentials without any manual export.
Gotcha
This is the approach AWS recommends but most tutorials show the manual export method because it is faster to explain.
aws sts get-session-token --duration-seconds 3600 --serial-number arn:aws:iam::123456789012:mfa/myuser --token-code 123456 ↓ Click command to explain
When to use this
Get temporary credentials when MFA is required on your account.
aws sts assume-role-with-web-identity --role-arn arn:aws:iam::123456789012:role/my-role --role-session-name my-session --web-identity-token $ID_TOKEN ↓ Click command to explain
When to use this
Federate into an AWS role using an OIDC token, such as the token GitHub Actions provides for keyless CI/CD deployments.
Gotcha
This is what powers GitHub Actions OIDC and similar keyless CI integrations, so no long-lived AWS access keys are stored anywhere.
aws sts decode-authorization-message --encoded-message <encoded-message> ↓ Click command to explain
When to use this
Decode the long encoded message AWS returns for certain authorization denials to see exactly which permission was missing.
Gotcha
Some IAM denial errors return an opaque base64-like blob instead of a plain reason, this command is the only way to read what it actually says.
aws sts get-federation-token --name my-federated-user --policy file://policy.json --duration-seconds 3600 ↓ Click command to explain
When to use this
Issue short-lived, scoped-down credentials for a federated user or application, such as a third-party tool that needs temporary limited access.
aws lambda list-functions --query "Functions[*].{Name:FunctionName,Runtime:Runtime,Modified:LastModified}" --output table ↓ Click command to explain
When to use this
See every Lambda function in the current region along with its runtime and last modified date.
aws lambda invoke --function-name my-function --payload file://event.json --cli-binary-format raw-in-base64-out response.json ↓ Click command to explain
--cli-binary-format raw-in-base64-out Required in AWS CLI v2 when passing a JSON payload file, tells the CLI not to double-encode it When to use this
Manually invoke a Lambda function with a test event and inspect its response.
Gotcha
--cli-binary-format raw-in-base64-out is required in AWS CLI v2 when passing a JSON payload, without it you get a validation error about base64 encoding, this is the most common Lambda invoke failure when following v1 tutorials on a v2 CLI.
aws lambda invoke --function-name my-function --invocation-type Event --payload file://event.json --cli-binary-format raw-in-base64-out response.json ↓ Click command to explain
--invocation-type Event Fire-and-forget async invocation instead of waiting for the result When to use this
Trigger a Lambda function without waiting for it to finish, useful for background processing.
Gotcha
invocation-type Event means fire-and-forget async, the response.json will contain only a 202 status code not the function result, check CloudWatch Logs for the actual output.
aws lambda update-function-code --function-name my-function --zip-file fileb://function.zip ↓ Click command to explain
When to use this
Push a new deployment package to an existing Lambda function.
Gotcha
fileb:// with a b prefix reads the file as binary, using file:// for a zip file causes a corrupted upload that may silently fail or produce a broken deployment.
aws lambda create-function --function-name my-function --runtime python3.12 --role arn:aws:iam::123456789012:role/lambda-role --handler lambda_function.lambda_handler --zip-file fileb://function.zip ↓ Click command to explain
When to use this
Create a brand-new Lambda function from a local deployment package.
aws lambda get-function --function-name my-function ↓ Click command to explain
When to use this
Inspect a function's configuration, code location, and current state.
aws lambda create-function-url-config --function-name my-function --auth-type NONE ↓ Click command to explain
When to use this
Expose a Lambda function directly over HTTPS without setting up API Gateway.
Gotcha
auth-type NONE makes the function publicly invokable by anyone with the URL, use AWS_IAM for private endpoints.
aws lambda list-event-source-mappings --function-name my-function ↓ Click command to explain
When to use this
See which SQS queues, DynamoDB streams, or Kinesis streams are wired to trigger a function.
aws lambda delete-function --function-name my-function ↓ Click command to explain
When to use this
Permanently remove a function that is no longer needed.
Gotcha
This immediately and permanently deletes the function and its configuration, there is no recycle bin or undo.
aws lambda add-permission --function-name my-function --statement-id allow-s3 --action lambda:InvokeFunction --principal s3.amazonaws.com --source-arn arn:aws:s3:::my-bucket ↓ Click command to explain
When to use this
Allow an AWS service like S3 or EventBridge to invoke a Lambda function as part of an event trigger.
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com ↓ Click command to explain
When to use this
Log Docker in to a private ECR registry so you can push or pull images.
Gotcha
The auth token is region-scoped, if you authenticate against us-east-1 and try to push to a repository in eu-west-1 it will fail with an unauthorized error, always specify the correct region.
aws ecr create-repository --repository-name my-app ↓ Click command to explain
When to use this
Create a new private container image repository.
aws ecr describe-repositories --query "repositories[*].{Name:repositoryName,URI:repositoryUri}" --output table ↓ Click command to explain
When to use this
See every ECR repository in the account and its full pull URI.
aws ecr list-images --repository-name my-app ↓ Click command to explain
When to use this
See every image digest and tag pushed to a repository.
aws ecr batch-delete-image --repository-name my-app --image-ids imageTag=old-tag ↓ Click command to explain
When to use this
Remove old or unused image tags to reduce storage costs.
Gotcha
ECR does not automatically delete old images, untagged images accumulate and generate storage costs, set a lifecycle policy to automate cleanup.
aws ecs list-clusters ↓ Click command to explain
When to use this
See every ECS cluster in the current region.
aws ecs describe-services --cluster my-cluster --services my-service ↓ Click command to explain
When to use this
Check the running count, desired count, and deployment status of an ECS service.
aws ecs update-service --cluster my-cluster --service my-service --desired-count 3 ↓ Click command to explain
When to use this
Scale an ECS service up or down without redeploying.
aws ecs execute-command --cluster my-cluster --task task-id --container my-container --interactive --command /bin/sh ↓ Click command to explain
When to use this
Debug a running ECS Fargate or EC2-backed task by getting an interactive shell inside its container.
Gotcha
This requires --enable-execute-command to have been set on the service or task definition AND the SSM Session Manager plugin installed locally, missing either one gives a confusing error that does not clearly identify which prerequisite is missing.
aws eks update-kubeconfig --region us-east-1 --name my-cluster ↓ Click command to explain
When to use this
Configure kubectl to connect to an EKS cluster so you can run kubectl commands against it.
Gotcha
If you run this with one IAM profile and then run kubectl commands under a different profile or role, kubectl will fail with You must be logged in to the server, the IAM identity used for update-kubeconfig must match or be mapped in the cluster's access configuration.
aws eks list-clusters ↓ Click command to explain
When to use this
See every EKS cluster in the current region.
aws eks describe-cluster --name my-cluster ↓ Click command to explain
When to use this
Inspect a cluster's endpoint, version, and networking configuration.
aws ec2 describe-vpcs --query "Vpcs[*].{ID:VpcId,CIDR:CidrBlock}" --output table ↓ Click command to explain
When to use this
See every VPC in the current region along with its CIDR block.
aws ec2 describe-subnets --filters Name=vpc-id,Values=vpc-12345678 ↓ Click command to explain
When to use this
List every subnet inside a specific VPC along with its availability zone and CIDR.
aws ec2 create-vpc --cidr-block 10.0.0.0/16 ↓ Click command to explain
When to use this
Create a new isolated network for a new environment or account.
Gotcha
A newly created VPC has no subnets, route tables, or internet gateway attached, it is an empty network shell until you build out the rest.
aws ec2 describe-route-tables --filters Name=vpc-id,Values=vpc-12345678 ↓ Click command to explain
When to use this
Inspect how traffic is routed within a VPC, such as whether a subnet has a route to an internet gateway.
aws ec2 describe-internet-gateways ↓ Click command to explain
When to use this
Check which internet gateway is attached to a VPC when debugging why instances can't reach the internet.
aws elbv2 describe-load-balancers --query "LoadBalancers[*].{Name:LoadBalancerName,DNS:DNSName,State:State.Code}" --output table ↓ Click command to explain
When to use this
See every Application or Network Load Balancer and its DNS name.
aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/my-targets/1234567890abcdef ↓ Click command to explain
When to use this
Debug why a load balancer is returning errors by checking whether its targets are passing health checks.
Gotcha
A target showing unhealthy usually means the health check path returns a non-200 response or the security group blocks the health check port, not that the instance itself is down.
aws route53 list-hosted-zones ↓ Click command to explain
When to use this
See every DNS hosted zone managed in the account.
aws route53 list-resource-record-sets --hosted-zone-id Z1234567890ABC ↓ Click command to explain
When to use this
See every DNS record configured within a specific hosted zone.
aws route53 change-resource-record-sets --hosted-zone-id Z1234567890ABC --change-batch file://change-batch.json ↓ Click command to explain
When to use this
Point a domain or subdomain at a new target, such as updating a CNAME after migrating a load balancer.
Gotcha
DNS changes take time to propagate based on the record's TTL, a low TTL before a planned migration makes future changes take effect faster.
aws logs describe-log-groups --query "logGroups[*].logGroupName" --output text ↓ Click command to explain
When to use this
See every log group in the account, such as Lambda function logs or ECS task logs.
aws logs tail /aws/lambda/my-function --follow ↓ Click command to explain
When to use this
Stream live logs from a Lambda function or any CloudWatch log group like a tail -f.
Gotcha
aws logs tail is a newer command that most developers do not know exists, it is far easier than get-log-events for live log monitoring.
aws logs filter-log-events --log-group-name /aws/lambda/my-function --filter-pattern ERROR --start-time 1718400000000 ↓ Click command to explain
When to use this
Search a log group for lines matching a specific pattern, such as ERROR, within a time range.
Gotcha
--start-time and --end-time are epoch milliseconds not seconds, passing seconds instead of milliseconds returns no results without an error message.
aws logs start-query --log-group-name /aws/lambda/my-function --start-time 1718400000 --end-time 1718486400 --query-string "fields @timestamp, @message | filter @message like /ERROR/ | sort @timestamp desc | limit 20" ↓ Click command to explain
When to use this
Run a CloudWatch Logs Insights query for powerful log analytics.
Gotcha
start-query returns a query ID immediately, you must then call get-query-results with that ID to retrieve the results once the query completes.
aws logs get-query-results --query-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ↓ Click command to explain
When to use this
Fetch the results of a previously started CloudWatch Logs Insights query.
Gotcha
Call this in a loop until status is Complete, the query may take several seconds depending on log volume.
aws ssm start-session --target i-1234567890abcdef0 ↓ Click command to explain
When to use this
Get a shell on an EC2 instance without SSH or open inbound ports.
Gotcha
Requires the SSM agent running on the instance AND the Session Manager plugin installed on your local machine AND the instance to have an IAM role with AmazonSSMManagedInstanceCore, missing any of these three gives different errors.
aws ssm get-parameter --name /my-app/database-url --with-decryption ↓ Click command to explain
When to use this
Read a configuration value or secret stored in Systems Manager Parameter Store.
Gotcha
--with-decryption is required for SecureString parameters, without it you get the encrypted value not the plaintext, the flag is silently ignored for String and StringList parameters so forgetting it only breaks SecureString.
aws ssm put-parameter --name /my-app/api-key --value mysecretvalue --type SecureString --overwrite ↓ Click command to explain
When to use this
Store or update a configuration value or encrypted secret in Parameter Store.
aws ssm send-command --document-name AWS-RunShellScript --targets Key=instanceids,Values=i-1234567890abcdef0 --parameters commands=["df -h"] ↓ Click command to explain
When to use this
Run a shell command on one or more EC2 instances without SSH.
aws cloudwatch put-metric-alarm --alarm-name high-cpu --metric-name CPUUtilization --namespace AWS/EC2 --statistic Average --period 300 --threshold 80 --comparison-operator GreaterThanThreshold --evaluation-periods 2 --alarm-actions arn:aws:sns:us-east-1:123456789012:my-topic --dimensions Name=InstanceId,Value=i-1234567890abcdef0 ↓ Click command to explain
When to use this
Set up an alarm that notifies an SNS topic when a metric like CPU utilization crosses a threshold.
aws cloudwatch get-metric-statistics --namespace AWS/EC2 --metric-name CPUUtilization --dimensions Name=InstanceId,Value=i-1234567890abcdef0 --start-time 2026-07-01T00:00:00Z --end-time 2026-07-02T00:00:00Z --period 3600 --statistics Average ↓ Click command to explain
When to use this
Pull historical metric values for a resource over a time range, such as average CPU over the last day.
aws cloudwatch describe-alarms --query "MetricAlarms[*].{Name:AlarmName,State:StateValue}" --output table ↓ Click command to explain
When to use this
See every configured alarm and whether it is currently OK, ALARM, or INSUFFICIENT_DATA.
aws rds describe-db-instances --query "DBInstances[*].{ID:DBInstanceIdentifier,Status:DBInstanceStatus,Engine:Engine}" --output table ↓ Click command to explain
When to use this
See every RDS instance in the account, its engine, and its current status.
aws rds create-db-snapshot --db-instance-identifier mydb --db-snapshot-identifier mydb-backup-2026-07-05 ↓ Click command to explain
When to use this
Take a manual, on-demand backup of a database before a risky migration or change.
aws rds delete-db-instance --db-instance-identifier mydb --skip-final-snapshot ↓ Click command to explain
When to use this
Permanently decommission a database instance that is no longer needed.
Gotcha
--skip-final-snapshot is commonly copied from tutorial and CI scripts but means your data is permanently destroyed with no backup, remove this flag on production databases and let AWS create a final snapshot before deletion.
aws rds restore-db-instance-from-db-snapshot --db-instance-identifier mydb-restored --db-snapshot-identifier mydb-backup-2026-07-05 --db-instance-class db.t3.micro ↓ Click command to explain
When to use this
Create a new database instance from an existing snapshot, such as recovering from an incident or standing up a test copy.
aws cloudformation deploy --template-file template.yaml --stack-name my-stack --capabilities CAPABILITY_IAM ↓ Click command to explain
When to use this
Create or update infrastructure defined in a CloudFormation template idempotently.
Gotcha
deploy is idempotent and creates the stack if it does not exist or updates it if it does, this is almost always what you want, use create-stack only if you specifically need to fail when the stack already exists.
aws cloudformation describe-stacks --stack-name my-stack --query "Stacks[0].Outputs" ↓ Click command to explain
When to use this
Read the output values from a CloudFormation stack like a load balancer URL or database endpoint.
aws cloudformation describe-stack-events --stack-name my-stack --query "StackEvents[?ResourceStatus=='FAILED']" --output table ↓ Click command to explain
When to use this
Find out why a CloudFormation stack deployment failed.
aws cloudformation delete-stack --stack-name my-stack ↓ Click command to explain
When to use this
Tear down every resource defined in a stack, such as decommissioning an entire environment.
Gotcha
This deletes every resource defined in the stack, for stacks containing RDS databases or S3 buckets the deletion may be blocked by DeletionPolicy or non-empty bucket errors.
aws secretsmanager get-secret-value --secret-id my-secret --query SecretString --output text | jq -r .password ↓ Click command to explain
When to use this
Retrieve and decode a specific key from a JSON-formatted secret in Secrets Manager.
Gotcha
SecretString is itself a JSON string not a JSON object, you cannot use --query to navigate into keys inside it directly, pipe the output to jq to extract a nested key.
aws secretsmanager create-secret --name my-secret --secret-string file://secret.json ↓ Click command to explain
When to use this
Store a new credential or API key in Secrets Manager.
aws secretsmanager put-secret-value --secret-id my-secret --secret-string newvalue ↓ Click command to explain
When to use this
Rotate or update the value of an existing secret without changing its ARN or name.
aws secretsmanager list-secrets --query "SecretList[*].{Name:Name,ARN:ARN}" --output table ↓ Click command to explain
When to use this
See every secret stored in Secrets Manager for the account and region.
AWS resolves credentials in this exact order. The first source that has valid credentials wins. This is the root cause of most AWS CLI authentication errors.
Command line options
--profile myprofile or --region us-east-1 These override everything else. If you pass --profile on the command line it wins regardless of environment variables or config files.
Environment variables
AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN, AWS_PROFILE If any of these are set in your shell they will be used. This is the most common cause of using the wrong credentials, which are often a leftover export from a previous assume-role session.
AWS SSO session cache
~/.aws/sso/cache/ If you use aws configure sso and the session has not expired the cached token is used here. If it has expired you get a confusing error rather than a prompt to log in again. Fix with aws sso login --profile yourprofile.
Named profile in config and credentials files
~/.aws/config and ~/.aws/credentials The profile named default is used automatically. The most common error here is a profile that exists in credentials but not in config or vice versa. Run aws configure list-profiles to see what is actually there.
Assumed role via source_profile
role_arn + source_profile in ~/.aws/config AWS CLI automatically calls sts assume-role and refreshes the temporary credentials. This is the right way to work with assumed roles and avoids manual export of credentials entirely.
EC2 instance profile or ECS task role
Metadata service at 169.254.169.254 Only available when running on EC2, ECS, Lambda, or similar AWS compute. If you are running locally and reach this step it means none of the above sources found credentials and the call will fail.
Check which identity is currently active
aws sts get-caller-identity Run this before any destructive command. Shows your Account ID, UserId, and ARN. If this fails your credentials are not configured correctly.
Check which profile is active and where credentials are coming from
aws configure list Shows whether each configuration value comes from an env variable, config file, or default. The source column tells you exactly which file or variable is winning.
List all configured profiles
aws configure list-profiles If your profile is not in this list the error will be The config profile X could not be found.
Check active credentials for a specific profile
aws sts get-caller-identity --profile myprofile Replace myprofile with your profile name. If this returns an error the profile credentials are expired or misconfigured.
Not sure which S3 command to use? Answer two questions.
aws s3 cp aws s3 cp ./file.txt s3://my-bucket/folder/file.txt aws s3 sync aws s3 sync ./local-folder s3://my-bucket/prefix/ --delete aws s3 mv aws s3 mv s3://source-bucket/file.txt s3://dest-bucket/file.txt aws s3 rm aws s3 rm s3://my-bucket/folder/ --recursive aws s3api aws s3api put-object --bucket my-bucket --key file.txt --body file.txt The AWS CLI is a single command-line tool that wraps every AWS service API behind one consistent interface, and for engineers who manage AWS infrastructure day to day it is often faster and more precise than clicking through the console. Almost every action available in the AWS Management Console has a direct CLI equivalent, but the CLI adds what the console cannot: it is scriptable, reproducible, and pipeable into other Unix tools like jq and grep, which makes it the backbone of CI/CD pipelines, cron jobs, and one-off investigations alike. Whether the task is checking why a Lambda function is failing, rotating a secret, or auditing which IAM policies are attached to a role, the CLI turns what would be several minutes of console navigation into a single reusable command.
The reason the AWS CLI shows up constantly in daily engineering work is that AWS environments are rarely static. Auto-scaling groups launch and terminate instances continuously, Lambda functions deploy multiple times a day, and IAM permissions get adjusted as teams and services change. Engineers are constantly checking the current state of the world: is this instance still running, did that deployment actually update the function code, does this role really have the permission it needs. Commands like aws sts get-caller-identity, aws ec2 describe-instances, and aws logs tail form the same kind of always-reached-for read loop that kubectl get and docker ps represent in their respective ecosystems, and most real AWS CLI usage is those few commands repeated with different arguments.
The single most important mental model for working with the AWS CLI is the credential chain: the ordered list of places the CLI looks for credentials before it gives up. Command-line flags beat environment variables, which beat the SSO cache, which beats named profiles in your config files, which beats an assumed role, which beats the EC2 or ECS metadata service. Almost every confusing AWS CLI authentication error traces back to a credential source further up this chain winning unexpectedly, whether a leftover AWS_PROFILE environment variable from a previous session, or an SSO token that quietly expired. Once that ordered list clicks, debugging authentication stops being guesswork: run aws configure list and aws sts get-caller-identity, and the winning source is right there in the output.
Three mistakes account for the overwhelming majority of AWS CLI frustration. The first is forgetting that --query returns null silently on a bad JMESPath expression instead of raising an error, which makes a typo in a query look like missing data. The second is confusing s3 cp with s3 sync: cp only touches the exact file or prefix you name, while sync recursively mirrors an entire folder and, combined with --delete, can permanently remove files that exist only in the destination. The third is running a destructive command like terminate-instances or delete-db-instance against the wrong account entirely, because a stale AWS_PROFILE or an expired SSO session silently fell back to a different set of credentials. Running aws sts get-caller-identity before any destructive command is the single habit that prevents the most expensive version of this mistake.