{"id":4753,"date":"2026-04-07T21:47:23","date_gmt":"2026-04-07T16:17:23","guid":{"rendered":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/"},"modified":"2026-04-07T21:47:23","modified_gmt":"2026-04-07T16:17:23","slug":"aws-best-practices-guide","status":"publish","type":"post","link":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/","title":{"rendered":"AWS Best Practices &#8211; Guide"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_80 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-69d53a101da08\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-69d53a101da08\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#AWS_Best_Practices_Why_Your_Infrastructure_is_a_Money_Pit_and_How_to_Stop_the_Bleeding\" >AWS Best Practices: Why Your Infrastructure is a Money Pit and How to Stop the Bleeding<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#1_IAM_Stop_Using_Managed_Policies_Immediately\" >1. IAM: Stop Using Managed Policies Immediately<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#2_The_NAT_Gateway_Scam_and_VPC_Endpoints\" >2. The NAT Gateway Scam and VPC Endpoints<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#3_Compute_Graviton_and_the_gp3_Tax\" >3. Compute: Graviton and the gp3 Tax<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#4_S3_Intelligent_Tiering_is_Not_a_Silver_Bullet\" >4. S3: Intelligent Tiering is Not a Silver Bullet<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#5_Networking_The_Cross-AZ_Data_Transfer_Trap\" >5. Networking: The Cross-AZ Data Transfer Trap<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#6_Observability_CloudWatch_is_a_Money_Pit\" >6. Observability: CloudWatch is a Money Pit<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#7_The_%E2%80%9CDefault_VPC%E2%80%9D_Disaster\" >7. The &#8220;Default VPC&#8221; Disaster<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#8_RDS_The_Proxy_and_the_Connection_Limit\" >8. RDS: The Proxy and the Connection Limit<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#9_Terraform_The_%E2%80%9CState%E2%80%9D_of_Chaos\" >9. Terraform: The &#8220;State&#8221; of Chaos<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#10_The_Reality_of_EKS\" >10. The Reality of EKS<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#11_Cost_Allocation_Tags_or_Death\" >11. Cost Allocation: Tags or Death<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#The_%E2%80%9CGotcha%E2%80%9D_Only_Experts_Know_The_us-east-1_Curse\" >The &#8220;Gotcha&#8221; Only Experts Know: The us-east-1 Curse<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#Related_Articles\" >Related Articles<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"AWS_Best_Practices_Why_Your_Infrastructure_is_a_Money_Pit_and_How_to_Stop_the_Bleeding\"><\/span>AWS Best Practices: Why Your Infrastructure is a Money Pit and How to Stop the Bleeding<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>I once worked at a fintech startup where we &#8220;followed the docs&#8221; to the letter. We set up a multi-AZ deployment for a high-traffic microservice, thinking we were being smart about availability. Three days later, the Head of Engineering walked into the room with a face the color of a CloudWatch alarm. Our NAT Gateway bill for the weekend was $14,000. We weren&#8217;t even doing anything complex; we were just pulling 5GB Docker images from an external registry every time a pod scaled, and those bits were traveling over the public internet through a NAT Gateway. It was a $14k lesson in why &#8220;default&#8221; settings are a trap.<\/p>\n<p>The problem is that AWS documentation is written by people who want you to use more AWS. They want you to click the &#8220;Enable&#8221; button on every managed service because it\u2019s &#8220;seamless.&#8221; In reality, every &#8220;seamless&#8221; integration is a hidden line item on your bill or a new way for your system to fail at 3 AM. This isn&#8217;t about &#8220;unlocking potential.&#8221; This is about survival in a cloud environment that is designed to over-provision your wallet. The following <b>aws best<\/b> practices are born from scars, not slide decks.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"1_IAM_Stop_Using_Managed_Policies_Immediately\"><\/span>1. IAM: Stop Using Managed Policies Immediately<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>AWS provides &#8220;Managed Policies&#8221; like <code>AdministratorAccess<\/code> or <code>AmazonS3FullAccess<\/code>. They are a security nightmare. If you attach <code>AmazonS3FullAccess<\/code> to a Lambda function, and that function has a remote code execution vulnerability, the attacker doesn&#8217;t just have your data; they have the ability to delete every bucket in your account. I\u2019ve seen a disgruntled contractor wipe a staging environment because the &#8220;Dev&#8221; role had <code>iam:*<\/code> permissions &#8220;just in case.&#8221;<\/p>\n<p>The &#8220;aws best&#8221; way to handle IAM is to write your own policies and use <code>Condition<\/code> blocks. If a service only needs to talk to one bucket, name that bucket. If it only needs to talk to that bucket from a specific VPC, enforce it.<\/p>\n<pre><code>{\n    \"Version\": \"2012-10-17\",\n    \"Statement\": [\n        {\n            \"Sid\": \"AllowS3AccessToSpecificBucket\",\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"s3:GetObject\",\n                \"s3:PutObject\"\n            ],\n            \"Resource\": \"arn:aws:s3:::production-customer-data-12345\/*\",\n            \"Condition\": {\n                \"StringEquals\": {\n                    \"aws:SourceVpc\": \"vpc-0a1b2c3d4e5f6g7h8\"\n                }\n            }\n        }\n    ]\n}\n<\/code><\/pre>\n<ul>\n<li><b>Pro-tip:<\/b> Use <code>iam:PassRole<\/code> restrictions. Without them, anyone with <code>ec2:RunInstances<\/code> can create a machine with an <code>Admin<\/code> role and escalate their privileges.<\/li>\n<li><b>Note to self:<\/b> Use <code>aws-vault<\/code> or AWS IAM Identity Center (formerly SSO). Never, ever let a developer put a <code>.csv<\/code> file with <code>AKIA...<\/code> keys on their local machine. It will end up in a public GitHub repo. It\u2019s not a matter of if, but when.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"2_The_NAT_Gateway_Scam_and_VPC_Endpoints\"><\/span>2. The NAT Gateway Scam and VPC Endpoints<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you are using a NAT Gateway, you are likely being overcharged. AWS charges $0.045 per GB of data processed. This sounds small until you realize that your internal logs, your container image pulls, and your database backups are all hitting that gateway if you haven&#8217;t configured your routing correctly. I\u2019ve seen companies spend more on NAT Gateways than on their actual EC2 compute.<\/p>\n<p>The fix is VPC Endpoints. Specifically, Gateway Endpoints for S3 and DynamoDB. They are free. They don&#8217;t charge for data transfer. If you aren&#8217;t using them, you are literally throwing money at Amazon for no reason.<\/p>\n<pre><code># Terraform snippet for an S3 Gateway Endpoint\nresource \"aws_vpc_endpoint\" \"s3\" {\n  vpc_id       = aws_vpc.main.id\n  service_name = \"com.amazonaws.us-east-1.s3\"\n  route_table_ids = [aws_route_table.private.id]\n}\n<\/code><\/pre>\n<p>For other services like Secrets Manager or EC2 APIs, use Interface Endpoints (PrivateLink). They aren&#8217;t free\u2014they have an hourly cost\u2014but the data processing fee is usually lower than a NAT Gateway for high-volume internal traffic. Stop letting your traffic loop out to the public internet just to talk to another AWS service in the same region.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"3_Compute_Graviton_and_the_gp3_Tax\"><\/span>3. Compute: Graviton and the gp3 Tax<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you are still running <code>t3<\/code> or <code>m5<\/code> instances, you are paying a legacy tax. AWS Graviton (the <code>6g<\/code>, <code>7g<\/code> series) is cheaper and faster for almost every workload. We migrated a fleet of Python-based microservices from <code>m5.large<\/code> to <code>m6g.large<\/code> and saw a 20% drop in latency and a 15% drop in cost. The only hurdle is your CI\/CD pipeline needs to build for <code>arm64<\/code>.<\/p>\n<p>Speaking of taxes, look at your EBS volumes. If they say <code>gp2<\/code>, change them to <code>gp3<\/code> right now. <code>gp2<\/code> ties your IOPS to the size of the disk. If you want 3,000 IOPS on <code>gp2<\/code>, you have to buy a 1TB disk. On <code>gp3<\/code>, you get 3,000 IOPS for free regardless of disk size, and the baseline price is 20% lower. It\u2019s a literal &#8220;click to save money&#8221; button in the console.<\/p>\n<blockquote><p>\n    <b>Pro-tip:<\/b> When moving to Graviton, you will hit the <code>exec format error<\/code> in your Docker containers. Use Docker Buildx to create multi-arch images. Don&#8217;t be the person who pushes an x86 image to an ARM node and wonders why the Kubelet is screaming.\n<\/p><\/blockquote>\n<pre><code># Build for both architectures\ndocker buildx build --platform linux\/amd64,linux\/arm64 -t 123456789012.dkr.ecr.us-east-1.amazonaws.com\/my-app:v1.0.2 --push .\n<\/code><\/pre>\n<h2><span class=\"ez-toc-section\" id=\"4_S3_Intelligent_Tiering_is_Not_a_Silver_Bullet\"><\/span>4. S3: Intelligent Tiering is Not a Silver Bullet<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The &#8220;aws best&#8221; practice guides often scream &#8220;Use S3 Intelligent Tiering!&#8221; This is dangerous advice for people with millions of small objects. Intelligent Tiering has a monitoring fee per object ($0.0025 per 1,000 objects). If you have 100 million 10KB files, you will pay $250 a month just for AWS to &#8220;monitor&#8221; files that would have cost you $20 to store in Standard tier.<\/p>\n<p>If your objects are smaller than 128KB, Intelligent Tiering will never move them to the Archive Instant Access tier anyway. You\u2019re paying for a service that does nothing. For small objects, use Lifecycle Policies to transition them to <code>ONEZONE_IA<\/code> or <code>GLACIER_INSTANT_RETRIEVAL<\/code> after 30 days, or better yet, bundle small files into larger archives before uploading.<\/p>\n<ul>\n<li><b>Rule 1:<\/b> Objects < 128KB stay in Standard.<\/li>\n<li><b>Rule 2:<\/b> Use <code>s3:PutObject<\/code> and disable ACLs. Bucket owner enforced is the only way to stay sane.<\/li>\n<li><b>Rule 3:<\/b> Versioning is not a backup. If you delete a bucket, the versions go with it. Use Cross-Region Replication (CRR) if you actually care about the data.<\/li>\n<li><b>Rule 4:<\/b> Set a <code>AbortIncompleteMultipartUpload<\/code> lifecycle rule. I once found 4TB of &#8220;ghost&#8221; data in a bucket from failed uploads that we were being billed for.<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"5_Networking_The_Cross-AZ_Data_Transfer_Trap\"><\/span>5. Networking: The Cross-AZ Data Transfer Trap<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>AWS charges $0.01 per GB for data transferred between Availability Zones (AZs). This sounds negligible. It isn&#8217;t. If you have a Kafka cluster in <code>us-east-1a<\/code> and your consumers are in <code>us-east-1b<\/code>, you are paying that fee for every single message. If you move 100TB a month, that\u2019s $1,000 just for the privilege of crossing a fiber optic cable in Northern Virginia.<\/p>\n<p>To fix this, use &#8220;AZ-Aware&#8221; routing. In Kubernetes, use <code>topologyKeys<\/code> or <code>TopologyAwareHints<\/code>. For RDS, try to keep your application servers in the same AZ as the primary writer. Yes, you need multi-AZ for failover, but your &#8220;happy path&#8221; traffic should stay within the same zone whenever possible.<\/p>\n<pre><code># Example Kubernetes Service with Topology Hints\napiVersion: v1\nkind: Service\nmetadata:\n  name: my-app-service\n  annotations:\n    service.kubernetes.io\/topology-mode: Auto\nspec:\n  selector:\n    app: my-app\n  ports:\n    - protocol: TCP\n      port: 80\n      targetPort: 8080\n<\/code><\/pre>\n<h2><span class=\"ez-toc-section\" id=\"6_Observability_CloudWatch_is_a_Money_Pit\"><\/span>6. Observability: CloudWatch is a Money Pit<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>CloudWatch Logs is one of the most expensive ways to store text. At $0.50 per GB ingested, it\u2019s a racket. I\u2019ve seen systems where the logging cost exceeded the compute cost because some developer left <code>DEBUG<\/code> logging on in production. &#8220;aws best&#8221; practices suggest using CloudWatch for everything. I suggest you don&#8217;t.<\/p>\n<p>Ingest your logs, but set a retention policy immediately. The default is &#8220;Never Expire.&#8221; That is a recipe for a bill that grows linearly until you die. Set it to 7 days, or 14 days. If you need long-term storage for compliance, use a Kinesis Firehose to stream those logs to S3 and query them with Athena. It is orders of magnitude cheaper.<\/p>\n<p>Also, stop using CloudWatch Custom Metrics if you have high cardinality. If you start tracking <code>customer_id<\/code> as a dimension in CloudWatch, your bill will explode. Each unique combination of dimensions is a new metric, and AWS charges per metric. Use OpenTelemetry and send that data to a Prometheus instance or a specialized vendor who doesn&#8217;t charge per-metric-line-item.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"7_The_%E2%80%9CDefault_VPC%E2%80%9D_Disaster\"><\/span>7. The &#8220;Default VPC&#8221; Disaster<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Every AWS account comes with a default VPC in every region. It has public subnets and an Internet Gateway. It is a playground for security breaches. The first thing I do in any new account is delete the default VPC. It forces you to actually think about your networking. If you don&#8217;t specify a subnet in your Terraform code, AWS will try to put it in the default VPC. If that VPC has an IGW, your &#8220;private&#8221; database might suddenly have a public IP address.<\/p>\n<p>I once saw a &#8220;hidden&#8221; RDS instance that had been running in a default VPC for two years. It was wide open to <code>0.0.0.0\/0<\/code> on port 5432. The only reason it wasn&#8217;t breached was that the password was 32 characters of random gibberish. We got lucky. Don&#8217;t rely on luck.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"8_RDS_The_Proxy_and_the_Connection_Limit\"><\/span>8. RDS: The Proxy and the Connection Limit<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you are using Lambda with RDS, you are going to have a bad time. Lambda scales horizontally so fast that it will exhaust the Postgres or MySQL connection pool in seconds. Each Lambda execution starts a new process, and if you aren&#8217;t careful, a new database connection. Postgres 14 on a <code>t3.medium<\/code> can&#8217;t handle 500 concurrent connections.<\/p>\n<p>Use RDS Proxy. It sits between your Lambda and your DB, pooling connections and handling the &#8220;zombie&#8221; connections that Lambda leaves behind. It also makes failovers faster because the proxy handles the DNS switch, not your application code.<\/p>\n<pre><code># Pro-tip: Check your DB connections with this SQL\nSELECT count(*), state FROM pg_stat_activity GROUP BY state;\n<\/code><\/pre>\n<p>If you see hundreds of &#8220;idle&#8221; connections, your application is leaking them. RDS Proxy will mitigate this, but it won&#8217;t fix your bad code. Fix the code, then add the proxy as a safety net.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"9_Terraform_The_%E2%80%9CState%E2%80%9D_of_Chaos\"><\/span>9. Terraform: The &#8220;State&#8221; of Chaos<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Infrastructure as Code (IaC) is not optional. But &#8220;aws best&#8221; practices often ignore how to manage the state file. If you are keeping your <code>terraform.tfstate<\/code> on your local machine, you are one <code>rm -rf<\/code> away from a very bad week. Use an S3 backend with DynamoDB locking. This is non-negotiable for teams.<\/p>\n<pre><code>terraform {\n  backend \"s3\" {\n    bucket         = \"my-company-terraform-state\"\n    key            = \"prod\/network\/terraform.tfstate\"\n    region         = \"us-east-1\"\n    dynamodb_table = \"terraform-lock\"\n    encrypt        = true\n  }\n}\n<\/code><\/pre>\n<p>And for the love of all that is holy, use <code>lifecycle { prevent_destroy = true }<\/code> on your VPCs, Databases, and S3 buckets. I\u2019ve seen a <code>terraform destroy<\/code> meant for a dev environment accidentally pointed at production because of an incorrectly set <code>AWS_PROFILE<\/code>. The <code>prevent_destroy<\/code> flag is the only thing that will save your job in that scenario.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"10_The_Reality_of_EKS\"><\/span>10. The Reality of EKS<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Everyone wants Kubernetes. Most people don&#8217;t need it. EKS is a &#8220;managed&#8221; service that still requires you to manage the VPC CNI, the CoreDNS configuration, the storage classes, and the upgrade path for the control plane. It is not &#8220;set and forget.&#8221;<\/p>\n<p>If you must use EKS, use <b>Karpenter<\/b> instead of the standard Cluster Autoscaler. The Cluster Autoscaler is slow; it waits for the AWS Auto Scaling Group to realize it needs a node, which then waits for the EC2 API. Karpenter talks directly to the EC2 Fleet API and can provision a node in sub-60 seconds. It also handles &#8220;bin-packing&#8221; better, moving your pods to the cheapest possible instance types automatically.<\/p>\n<blockquote><p>\n    <b>Pro-tip:<\/b> EKS Fargate is a trap for high-throughput apps. You pay a premium for the &#8220;serverless&#8221; nature, but you lose control over networking (no DaemonSets) and it\u2019s significantly more expensive than running managed node groups with Spot instances.\n<\/p><\/blockquote>\n<h2><span class=\"ez-toc-section\" id=\"11_Cost_Allocation_Tags_or_Death\"><\/span>11. Cost Allocation: Tags or Death<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you don&#8217;t have a tagging policy, you don&#8217;t have a budget. You need to enforce tags at the IAM level. If a resource doesn&#8217;t have a <code>Project<\/code>, <code>Environment<\/code>, and <code>Owner<\/code> tag, the <code>RunInstances<\/code> call should fail. This is the only way to track down who is running that <code>p3.16xlarge<\/code> instance that\u2019s been idle for three weeks.<\/p>\n<pre><code>{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"EnforceTagging\",\n      \"Effect\": \"Deny\",\n      \"Action\": \"ec2:RunInstances\",\n      \"Resource\": \"arn:aws:ec2:*:*:instance\/*\",\n      \"Condition\": {\n        \"Null\": {\n          \"aws:RequestTag\/Project\": \"true\"\n        }\n      }\n    }\n  ]\n}\n<\/code><\/pre>\n<p>Once you have tags, use the AWS Cost and Usage Report (CUR). Cost Explorer is for managers. CUR + Athena is for SREs. It allows you to write SQL queries to find out exactly which S3 bucket is responsible for that $500 &#8220;Data Transfer&#8221; charge.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"The_%E2%80%9CGotcha%E2%80%9D_Only_Experts_Know_The_us-east-1_Curse\"><\/span>The &#8220;Gotcha&#8221; Only Experts Know: The <code>us-east-1<\/code> Curse<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Everyone defaults to <code>us-east-1<\/code>. It\u2019s the oldest region. It has the most services. It also fails the most. When AWS has a global outage, it almost always starts in <code>us-east-1<\/code>. If you are building something new, go to <code>us-east-2<\/code> (Ohio) or <code>us-west-2<\/code> (Oregon). They are newer, the hardware is generally fresher, and they are significantly more stable. If you must stay in <code>us-east-1<\/code>, ensure your architecture is truly multi-AZ, because &#8220;AZ-1&#8221; in one account is not the same physical building as &#8220;AZ-1&#8221; in another account. Use AZ IDs (e.g., <code>use1-az1<\/code>) to map your infrastructure if you are doing cross-account networking.<\/p>\n<p>AWS is a collection of primitives, not a finished product. The &#8220;best&#8221; way to use it is to treat every managed service with suspicion, every default setting as a potential bill spike, and every IAM permission as a potential security hole. Stop chasing the hype of new service releases and start focusing on the boring, fundamental work of locking down your network and optimizing your data transfer. Your on-call rotation and your company&#8217;s bank account will thank you.<\/p>\n<p>Stop clicking buttons in the console. Write the code. Lock the state. Turn off the NAT Gateway. Go home.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Related_Articles\"><\/span>Related Articles<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Explore more insights and best practices:<\/p>\n<ul>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/docker-compose-guide\/\">Docker Compose Guide<\/a><\/li>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/creating-and-assigning-custom-licensing-options-in-microsoft-office-365\/\">Creating And Assigning Custom Licensing Options In Microsoft Office 365<\/a><\/li>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/kali-linux-virtualbox-installation\/\">Kali Linux Virtualbox Installation<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>AWS Best Practices: Why Your Infrastructure is a Money Pit and How to Stop the Bleeding I once worked at a fintech startup where we &#8220;followed the docs&#8221; to the letter. We set up a multi-AZ deployment for a high-traffic microservice, thinking we were being smart about availability. Three days later, the Head of Engineering &#8230; <a title=\"AWS Best Practices &#8211; Guide\" class=\"read-more\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/\" aria-label=\"Read more  on AWS Best Practices &#8211; Guide\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4753","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>AWS Best Practices - Guide - ITSupportWale<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"AWS Best Practices - Guide - ITSupportWale\" \/>\n<meta property=\"og:description\" content=\"AWS Best Practices: Why Your Infrastructure is a Money Pit and How to Stop the Bleeding I once worked at a fintech startup where we &#8220;followed the docs&#8221; to the letter. We set up a multi-AZ deployment for a high-traffic microservice, thinking we were being smart about availability. Three days later, the Head of Engineering ... Read more\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/\" \/>\n<meta property=\"og:site_name\" content=\"ITSupportWale\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\" \/>\n<meta property=\"article:published_time\" content=\"2026-04-07T16:17:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"512\" \/>\n\t<meta property=\"og:image:height\" content=\"512\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Techie\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Techie\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/\"},\"author\":{\"name\":\"Techie\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\"},\"headline\":\"AWS Best Practices &#8211; Guide\",\"datePublished\":\"2026-04-07T16:17:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/\"},\"wordCount\":2077,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/\",\"name\":\"AWS Best Practices - Guide - ITSupportWale\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\"},\"datePublished\":\"2026-04-07T16:17:23+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/itsupportwale.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AWS Best Practices &#8211; Guide\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"name\":\"ITSupportWale\",\"description\":\"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides\",\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\",\"name\":\"itsupportwale\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"contentUrl\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"width\":1119,\"height\":144,\"caption\":\"itsupportwale\"},\"image\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\",\"name\":\"Techie\",\"sameAs\":[\"https:\/\/itsupportwale.com\",\"iswblogadmin\"],\"url\":\"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"AWS Best Practices - Guide - ITSupportWale","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/","og_locale":"en_US","og_type":"article","og_title":"AWS Best Practices - Guide - ITSupportWale","og_description":"AWS Best Practices: Why Your Infrastructure is a Money Pit and How to Stop the Bleeding I once worked at a fintech startup where we &#8220;followed the docs&#8221; to the letter. We set up a multi-AZ deployment for a high-traffic microservice, thinking we were being smart about availability. Three days later, the Head of Engineering ... Read more","og_url":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/","og_site_name":"ITSupportWale","article_publisher":"https:\/\/www.facebook.com\/Itsupportwale-298547177495978","article_published_time":"2026-04-07T16:17:23+00:00","og_image":[{"width":512,"height":512,"url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png","type":"image\/png"}],"author":"Techie","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Techie","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#article","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/"},"author":{"name":"Techie","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d"},"headline":"AWS Best Practices &#8211; Guide","datePublished":"2026-04-07T16:17:23+00:00","mainEntityOfPage":{"@id":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/"},"wordCount":2077,"commentCount":0,"publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/","url":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/","name":"AWS Best Practices - Guide - ITSupportWale","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/#website"},"datePublished":"2026-04-07T16:17:23+00:00","breadcrumb":{"@id":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/itsupportwale.com\/blog\/aws-best-practices-guide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/itsupportwale.com\/blog\/"},{"@type":"ListItem","position":2,"name":"AWS Best Practices &#8211; Guide"}]},{"@type":"WebSite","@id":"https:\/\/itsupportwale.com\/blog\/#website","url":"https:\/\/itsupportwale.com\/blog\/","name":"ITSupportWale","description":"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides","publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/itsupportwale.com\/blog\/#organization","name":"itsupportwale","url":"https:\/\/itsupportwale.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","contentUrl":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","width":1119,"height":144,"caption":"itsupportwale"},"image":{"@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Itsupportwale-298547177495978"]},{"@type":"Person","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d","name":"Techie","sameAs":["https:\/\/itsupportwale.com","iswblogadmin"],"url":"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/"}]}},"_links":{"self":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4753","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/comments?post=4753"}],"version-history":[{"count":0,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4753\/revisions"}],"wp:attachment":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/media?parent=4753"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/categories?post=4753"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/tags?post=4753"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}