<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: KloudAudit</title>
    <description>The latest articles on DEV Community by KloudAudit (@kloudaudit).</description>
    <link>https://dev.to/kloudaudit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3901141%2F94cd118a-e8f6-48f1-8a3f-bbce5ce0e1b8.png</url>
      <title>DEV Community: KloudAudit</title>
      <link>https://dev.to/kloudaudit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kloudaudit"/>
    <language>en</language>
    <item>
      <title>How to cut your AWS RDS costs by 65% in 20 minutes (without touching production)</title>
      <dc:creator>KloudAudit</dc:creator>
      <pubDate>Wed, 13 May 2026 11:37:30 +0000</pubDate>
      <link>https://dev.to/kloudaudit/how-to-cut-your-aws-rds-costs-by-65-in-20-minutes-without-touching-production-2aj8</link>
      <guid>https://dev.to/kloudaudit/how-to-cut-your-aws-rds-costs-by-65-in-20-minutes-without-touching-production-2aj8</guid>
      <description>&lt;p&gt;This is the single most common finding in every cloud bill I audit.&lt;/p&gt;

&lt;p&gt;Dev and staging RDS instances running 24/7 at production size.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;db.r5.xlarge&lt;/code&gt; costs &lt;strong&gt;$876/month&lt;/strong&gt; running continuously. If your team uses it 8 hours a day on weekdays, you're paying for 720 hours and using 170. That's a &lt;strong&gt;76% waste rate&lt;/strong&gt; on a single instance.&lt;/p&gt;

&lt;p&gt;The fix takes 20 minutes and touches nothing in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem in numbers
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.r5.xlarge on-demand:  $876/month  (720 hrs)
db.r5.xlarge scheduled:  $306/month  (252 hrs — weekdays 8am-7pm)
Monthly saving:          $570/month
Annual saving:           $6,840/year
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multiply that by 2-3 dev/staging environments and you're looking at &lt;strong&gt;$15,000–$20,000/year&lt;/strong&gt; on instances that sleep most of the time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Find your idle RDS instances
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all RDS instances with their sizes and status&lt;/span&gt;
aws rds describe-db-instances &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'DBInstances[*].{ID:DBInstanceIdentifier,Class:DBInstanceClass,Status:DBInstanceStatus,MultiAZ:MultiAZ}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for anything that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has "dev", "staging", "test", or "qa" in the name&lt;/li&gt;
&lt;li&gt;Is the same instance class as production&lt;/li&gt;
&lt;li&gt;Has Multi-AZ enabled (almost never needed for dev)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 2: Create the IAM role
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; trust-policy.json &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "lambda.amazonaws.com" },
    "Action": "sts:AssumeRole"
  }]
}
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;aws iam create-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; rds-scheduler-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--assume-role-policy-document&lt;/span&gt; file://trust-policy.json

aws iam attach-role-policy &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role-name&lt;/span&gt; rds-scheduler-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-arn&lt;/span&gt; arn:aws:iam::aws:policy/AmazonRDSFullAccess
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Create the Lambda function
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# rds_scheduler.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;rds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;rds&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 'start' or 'stop'
&lt;/span&gt;    &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RDS_INSTANCES&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;instance_id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;stop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stop_db_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DBInstanceIdentifier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Stopped: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;start&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;rds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_db_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DBInstanceIdentifier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Started: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Error on &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;instance_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;done&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;action&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;instances&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zip scheduler.zip rds_scheduler.py

aws lambda create-function &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; rds-scheduler &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--runtime&lt;/span&gt; python3.12 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt; arn:aws:iam::YOUR_ACCOUNT_ID:role/rds-scheduler-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--handler&lt;/span&gt; rds_scheduler.handler &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--zip-file&lt;/span&gt; fileb://scheduler.zip &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--environment&lt;/span&gt; &lt;span class="s2"&gt;"Variables={RDS_INSTANCES=your-dev-db,your-staging-db}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Create the EventBridge schedules
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stop at 7pm every weekday&lt;/span&gt;
&lt;span class="c"&gt;# Adjust UTC offset for your timezone — CET/Warsaw is UTC+1, so 18:00 UTC = 7pm local&lt;/span&gt;
aws events put-rule &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"StopDevRDS"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--schedule-expression&lt;/span&gt; &lt;span class="s2"&gt;"cron(0 18 ? * MON-FRI *)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--state&lt;/span&gt; ENABLED

&lt;span class="c"&gt;# Start at 8am every weekday&lt;/span&gt;
aws events put-rule &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"StartDevRDS"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--schedule-expression&lt;/span&gt; &lt;span class="s2"&gt;"cron(0 7 ? * MON-FRI *)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--state&lt;/span&gt; ENABLED

&lt;span class="c"&gt;# Get your Lambda ARN&lt;/span&gt;
&lt;span class="nv"&gt;LAMBDA_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws lambda get-function &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; rds-scheduler &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Configuration.FunctionArn'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Add targets&lt;/span&gt;
aws events put-targets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rule&lt;/span&gt; StopDevRDS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--targets&lt;/span&gt; &lt;span class="s2"&gt;"Id=1,Arn=&lt;/span&gt;&lt;span class="nv"&gt;$LAMBDA_ARN&lt;/span&gt;&lt;span class="s2"&gt;,Input='{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;action&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;stop&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}'"&lt;/span&gt;

aws events put-targets &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rule&lt;/span&gt; StartDevRDS &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--targets&lt;/span&gt; &lt;span class="s2"&gt;"Id=1,Arn=&lt;/span&gt;&lt;span class="nv"&gt;$LAMBDA_ARN&lt;/span&gt;&lt;span class="s2"&gt;,Input='{&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;action&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;start&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}'"&lt;/span&gt;

&lt;span class="c"&gt;# Allow EventBridge to invoke Lambda&lt;/span&gt;
aws lambda add-permission &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; rds-scheduler &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--statement-id&lt;/span&gt; allow-eventbridge &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--action&lt;/span&gt; lambda:InvokeFunction &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--principal&lt;/span&gt; events.amazonaws.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--source-arn&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;aws events describe-rule &lt;span class="nt"&gt;--name&lt;/span&gt; StopDevRDS &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Arn'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5: Downsize the instance too
&lt;/h2&gt;

&lt;p&gt;While you're here — dev doesn't need a &lt;code&gt;db.r5.xlarge&lt;/code&gt;. Drop to &lt;code&gt;db.t3.medium&lt;/code&gt; for another 70% saving:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws rds modify-db-instance &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-instance-identifier&lt;/span&gt; your-dev-db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-instance-class&lt;/span&gt; db.t3.medium &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--apply-immediately&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combined result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.r5.xlarge 24/7:       $876/month  (original)
db.r5.xlarge scheduled:  $306/month  (schedule only)
db.t3.medium scheduled:  $89/month   (schedule + downsize)

Annual saving:           $9,444/year — from one dev database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6: Add a wake-up Slack command (optional)
&lt;/h2&gt;

&lt;p&gt;Your team will occasionally need the DB outside hours. Give them a self-service way to start it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a Lambda function URL&lt;/span&gt;
aws lambda create-function-url-config &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; rds-scheduler &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--auth-type&lt;/span&gt; NONE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in Slack: Apps → Slash Commands → &lt;code&gt;/start-devdb&lt;/code&gt; → point to the URL with body &lt;code&gt;{"action": "start"}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Engineers can start the DB themselves without waiting for someone with AWS console access.&lt;/p&gt;




&lt;h2&gt;
  
  
  What this looks like in real teams
&lt;/h2&gt;

&lt;p&gt;I've helped teams set this up in about 20 minutes. The conversation afterwards is always the same:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"I can't believe we were paying for that for 14 months."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not because they didn't know. Because nobody sat down and looked.&lt;/p&gt;

&lt;p&gt;This is one of 18 checks in &lt;a href="https://www.kloudaudit.eu" rel="noopener noreferrer"&gt;KloudAudit&lt;/a&gt; — a free self-guided cloud cost audit that walks through all of these systematically. No AWS credentials required. Takes 15 minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Find idle RDS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws rds describe-db-instances --query ...&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stop instance now&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws rds stop-db-instance --db-instance-identifier NAME&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start instance now&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws rds start-db-instance --db-instance-identifier NAME&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check instance state&lt;/td&gt;
&lt;td&gt;&lt;code&gt;aws rds describe-db-instances --db-instance-identifier NAME --query 'DBInstances[0].DBInstanceStatus'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;What's your team's current RDS setup — scheduled or running 24/7?&lt;/p&gt;

&lt;p&gt;Drop your setup in the comments — genuinely curious how common this is.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The 5 AWS charges silently draining your budget (and how to fix each one)</title>
      <dc:creator>KloudAudit</dc:creator>
      <pubDate>Sun, 03 May 2026 18:29:14 +0000</pubDate>
      <link>https://dev.to/kloudaudit/the-5-aws-charges-silently-draining-your-budget-and-how-to-fix-each-one-4ha7</link>
      <guid>https://dev.to/kloudaudit/the-5-aws-charges-silently-draining-your-budget-and-how-to-fix-each-one-4ha7</guid>
      <description>&lt;h1&gt;
  
  
  The 5 AWS charges silently draining your budget (and how to fix each one)
&lt;/h1&gt;

&lt;p&gt;I've reviewed a lot of cloud bills over 7 years as a DevOps engineer.&lt;/p&gt;

&lt;p&gt;The waste isn't exotic. It's not misconfigured Kubernetes clusters or obscure data transfer fees nobody knew existed. It's the same five things, over and over, on teams that genuinely believe they're managing costs well.&lt;/p&gt;

&lt;p&gt;Here's what they are — and exactly how to fix each one.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Dev and staging RDS running 24/7
&lt;/h2&gt;

&lt;p&gt;Your production database needs to run continuously. Your dev database does not.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;db.r5.xlarge&lt;/code&gt; runs ~$876/month. If your team uses it 8 hours a day on weekdays, you're paying for 720 hours and using roughly 170. That's $626/month funding nothing.&lt;/p&gt;

&lt;p&gt;The fix is a Lambda schedule. Takes 20 minutes to set up, runs forever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stop dev RDS at 7pm every weekday&lt;/span&gt;
aws events put-rule &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"StopDevRDS"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--schedule-expression&lt;/span&gt; &lt;span class="s2"&gt;"cron(0 17 ? * MON-FRI *)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--state&lt;/span&gt; ENABLED

&lt;span class="c"&gt;# Start it at 8am&lt;/span&gt;
aws events put-rule &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"StartDevRDS"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--schedule-expression&lt;/span&gt; &lt;span class="s2"&gt;"cron(0 8 ? * MON-FRI *)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--state&lt;/span&gt; ENABLED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Typical saving: 65% on affected instances.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The objection I always hear: &lt;em&gt;"But what if someone needs it on the weekend?"&lt;/em&gt; In 7 years I've seen this come up twice. The fix: add a manual start button in your internal tooling. A single Lambda invocation.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Everything on On-Demand pricing
&lt;/h2&gt;

&lt;p&gt;On-Demand is the rack rate. The price AWS publishes because they have to, not because they expect serious workloads to stay there.&lt;/p&gt;

&lt;p&gt;If you've had stable compute running for 6+ months — and most teams have — you're paying a 30-45% premium for flexibility you're not using.&lt;/p&gt;

&lt;p&gt;Compute Savings Plans are the easiest path. No instance family commitment, no region lock-in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# See exactly how much you'd save&lt;/span&gt;
aws savingsplans describe-savings-plans-purchase-recommendation &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--savings-plans-type&lt;/span&gt; COMPUTE_SP &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--term-in-years&lt;/span&gt; ONE_YEAR &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--payment-option&lt;/span&gt; NO_UPFRONT &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--lookback-period-in-days&lt;/span&gt; THIRTY_DAYS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run that. Read the output. The "Estimated Monthly Savings" figure is money you're leaving on the table every month you wait.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical saving: 30-45% on covered compute. Zero architecture changes required.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Unattached EBS volumes
&lt;/h2&gt;

&lt;p&gt;When you terminate an EC2 instance, AWS doesn't automatically delete the attached EBS volume. Unless you explicitly configured it to do so when you launched the instance, the volume sits there — charged at $0.10/GB/month — indefinitely.&lt;/p&gt;

&lt;p&gt;Find them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-volumes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;status,Values&lt;span class="o"&gt;=&lt;/span&gt;available &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Volumes[*].{ID:VolumeId,Size:Size,Created:CreateTime,Type:VolumeType}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Review the output. Anything created more than 30 days ago from an instance that no longer exists is almost certainly orphaned. Snapshot it for $0.05/GB/month if you're not sure, then delete the volume.&lt;/p&gt;

&lt;p&gt;I've found $200–$1,400/month from this command alone. The worst case I've seen: a team that migrated to EKS 18 months prior and left 67 volumes from their old EC2 fleet running the whole time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical saving: variable, but this takes 10 minutes to audit.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4. S3 storage never tiered
&lt;/h2&gt;

&lt;p&gt;S3 Standard is $0.023/GB/month. S3 Glacier Instant Retrieval is $0.004/GB/month.&lt;/p&gt;

&lt;p&gt;Your logs from 2023 don't need Standard. Neither do your backups, your old deployment artifacts, or the compliance exports nobody has opened since they were generated.&lt;/p&gt;

&lt;p&gt;A lifecycle policy fixes this automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3api put-bucket-lifecycle-configuration &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bucket&lt;/span&gt; your-bucket-name &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--lifecycle-configuration&lt;/span&gt; &lt;span class="s1"&gt;'{
    "Rules": [{
      "ID": "AutoTier",
      "Status": "Enabled",
      "Filter": {"Prefix": ""},
      "Transitions": [
        {"Days": 30, "StorageClass": "STANDARD_IA"},
        {"Days": 90, "StorageClass": "GLACIER_IR"}
      ]
    }]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set it once. It runs forever. Data moves through tiers automatically as it ages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typical saving: 30-60% on storage older than 90 days.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  5. NAT Gateway data processing charges
&lt;/h2&gt;

&lt;p&gt;This one surprises people every time.&lt;/p&gt;

&lt;p&gt;NAT Gateway charges $0.045 per GB processed — in both directions. If your microservices are calling AWS APIs (S3, DynamoDB, SQS) through a NAT Gateway instead of VPC endpoints, you're paying per-GB for every single request.&lt;/p&gt;

&lt;p&gt;At scale this adds up fast. I've seen teams with $800/month NAT Gateway bills that dropped to $60 after adding two free endpoints.&lt;/p&gt;

&lt;p&gt;The S3 and DynamoDB Gateway endpoints are free:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Free endpoint for S3 — traffic no longer routes through NAT&lt;/span&gt;
aws ec2 create-vpc-endpoint &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; vpc-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--service-name&lt;/span&gt; com.amazonaws.eu-west-1.s3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--route-table-ids&lt;/span&gt; rtb-xxxxxxxxx

&lt;span class="c"&gt;# Free endpoint for DynamoDB&lt;/span&gt;
aws ec2 create-vpc-endpoint &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; vpc-xxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--service-name&lt;/span&gt; com.amazonaws.eu-west-1.dynamodb &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--route-table-ids&lt;/span&gt; rtb-xxxxxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Typical saving: 10-40% of your NAT Gateway bill.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The pattern underneath all of this
&lt;/h2&gt;

&lt;p&gt;None of these are obscure. Every experienced AWS engineer knows they exist.&lt;/p&gt;

&lt;p&gt;The reason they accumulate anyway is always the same: the team is busy, the bill is complex, and nobody has sat down to look systematically. Cost Explorer shows you the numbers. It doesn't tell you which specific instances to reschedule, which volumes are orphaned, or which buckets have never had a lifecycle rule.&lt;/p&gt;

&lt;p&gt;That's the gap.&lt;/p&gt;




&lt;h2&gt;
  
  
  A tool I built for exactly this
&lt;/h2&gt;

&lt;p&gt;I got tired of doing this analysis manually on every engagement, so I built &lt;a href="https://www.kloudaudit.eu" rel="noopener noreferrer"&gt;KloudAudit&lt;/a&gt; — a structured 18-checkpoint audit that walks through all five of these (and 13 more) with savings estimates specific to your bill size.&lt;/p&gt;

&lt;p&gt;Free to run. Takes 15 minutes. No AWS account access required — you answer questions about your own setup, and it tells you what to fix and in what order.&lt;/p&gt;

&lt;p&gt;If you write about cloud costs or DevOps, I also built a &lt;strong&gt;free embeddable savings calculator&lt;/strong&gt; your readers can use directly on your articles. One script tag, no signup, no cost: &lt;a href="https://www.kloudaudit.eu/widget/" rel="noopener noreferrer"&gt;kloudaudit.eu/widget/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;What's the most surprising cloud cost you've discovered? I'm collecting war stories — drop it in the comments.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The 5 AWS charges silently draining your budget (and how to fix each one)</title>
      <dc:creator>KloudAudit</dc:creator>
      <pubDate>Thu, 30 Apr 2026 06:39:09 +0000</pubDate>
      <link>https://dev.to/kloudaudit/the-5-aws-charges-silently-draining-your-budget-and-how-to-fix-each-one-249n</link>
      <guid>https://dev.to/kloudaudit/the-5-aws-charges-silently-draining-your-budget-and-how-to-fix-each-one-249n</guid>
      <description>&lt;p&gt;Every AWS bill tells a story. After couple of years as a DevOps engineer reviewing cloud infrastructure, I've learned to read that story, and it almost always has the same five chapters.&lt;br&gt;
These aren't exotic edge cases. They show up on the bills of well-run teams with experienced engineers. They survive because cloud billing is complex, everyone is busy, and "we'll optimise later" is the most expensive phrase in engineering.&lt;br&gt;
Here's what to look for — and exactly how to fix each one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Dev/Staging RDS Running 24/7&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What it costs: A db.r5.xlarge running continuously costs ~$876/month. If it's only used 8 hours a day on weekdays, you're paying for 720 hours and using ~170.&lt;/p&gt;

&lt;p&gt;Why it happens: The database got created for a sprint, the sprint ended, and nobody scheduled a shutdown.&lt;/p&gt;

&lt;p&gt;The fix — Lambda stop/start schedule (20 minutes to implement):&lt;/p&gt;

&lt;p&gt;`# Create an IAM role for Lambda with RDS stop/start permissions&lt;br&gt;
aws iam create-role --role-name RDSScheduler \&lt;br&gt;
  --assume-role-policy-document file://lambda-trust-policy.json&lt;/p&gt;

&lt;h1&gt;
  
  
  Stop RDS at 7pm weekdays
&lt;/h1&gt;

&lt;p&gt;aws events put-rule \&lt;br&gt;
  --name "StopDevRDS" \&lt;br&gt;
  --schedule-expression "cron(0 17 ? * MON-FRI *)"&lt;/p&gt;

&lt;h1&gt;
  
  
  Start RDS at 8am weekdays
&lt;/h1&gt;

&lt;p&gt;aws events put-rule \&lt;br&gt;
  --name "StartDevRDS" \&lt;br&gt;
  --schedule-expression "cron(0 8 ? * MON-FRI *)"`&lt;/p&gt;

&lt;p&gt;Savings: 65% reduction on affected instances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Everything on On-Demand Pricing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What it costs: On-Demand is the list price the most expensive way to run EC2. If you've had stable workloads running for 6+ months, you're paying a significant premium for flexibility you're not using.&lt;br&gt;
Why it happens: Reservations require commitment and upfront analysis. On-Demand requires neither.&lt;/p&gt;

&lt;p&gt;The fix — Compute Savings Plans:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shell&lt;br&gt;
bash# Check your On-Demand spend for the last 3 months&lt;br&gt;
aws ce get-cost-and-usage \&lt;br&gt;
  --time-period Start=2026-01-01,End=2026-04-01 \&lt;br&gt;
  --granularity MONTHLY \&lt;br&gt;
  --filter '{"Dimensions":{"Key":"PURCHASE_TYPE","Values":["On Demand"]}}' \&lt;br&gt;
  --metrics BlendedCost&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Check Savings Plans recommendations
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;shell&lt;br&gt;
aws savingsplans describe-savings-plans-purchase-recommendation \&lt;br&gt;
  --savings-plans-type COMPUTE_SP \&lt;br&gt;
  --term-in-years ONE_YEAR \&lt;br&gt;
  --payment-option NO_UPFRONT&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Purchase a 1-year no-upfront Compute Savings Plan for your baseline usage. Zero architecture change. Zero risk.&lt;/p&gt;

&lt;p&gt;Savings: 30–45% on covered compute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Unattached EBS Volumes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What it costs: $0.10/GB/month sounds trivial. 50 forgotten 100GB volumes from a migration two years ago = $500/month. Every month. For nothing.&lt;/p&gt;

&lt;p&gt;Why it happens: When you terminate an EC2 instance, AWS doesn't automatically delete the attached EBS volume unless you explicitly configured it to do so.&lt;br&gt;
The fix — find and review them in 60 seconds:&lt;/p&gt;

&lt;p&gt;bash# List all unattached EBS volumes with their size and creation date&lt;/p&gt;

&lt;p&gt;&lt;code&gt;aws ec2 describe-volumes \&lt;br&gt;
  --filters Name=status,Values=available \&lt;br&gt;
  --query 'Volumes[*].{ID:VolumeId,Size:Size,Created:CreateTime,Type:VolumeType}' \&lt;br&gt;
  --output table&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;# Delete a specific volume (after verifying you don't need it)&lt;br&gt;
aws ec2 delete-volume --volume-id vol-xxxxxxxxxxxxxxxxx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Before deleting: create a snapshot if there's any chance the data is needed. Snapshots cost ~$0.05/GB/month — a fraction of the volume cost.&lt;br&gt;
Savings: variable, but I've seen $200–$1,200/month from this alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. S3 Storage Never Tiered&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What it costs: S3 Standard is $0.023/GB/month. S3 Glacier Instant Retrieval is $0.004/GB/month. Data from 2022 that nobody has accessed sitting in Standard costs 5.75x more than it needs to.&lt;br&gt;
Why it happens: Lifecycle rules require deliberate configuration. Default bucket settings keep everything in Standard forever.&lt;/p&gt;

&lt;p&gt;The fix — lifecycle policy (5 minutes):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;bash# Apply intelligent tiering lifecycle rule to a bucket&lt;br&gt;
aws s3api put-bucket-lifecycle-configuration \&lt;br&gt;
  --bucket your-bucket-name \&lt;br&gt;
  --lifecycle-configuration '{&lt;br&gt;
    "Rules": [{&lt;br&gt;
      "ID": "IntelligentTiering",&lt;br&gt;
      "Status": "Enabled",&lt;br&gt;
      "Filter": {"Prefix": ""},&lt;br&gt;
      "Transitions": [&lt;br&gt;
        {"Days": 30, "StorageClass": "STANDARD_IA"},&lt;br&gt;
        {"Days": 90, "StorageClass": "GLACIER_IR"}&lt;br&gt;
      ]&lt;br&gt;
    }]&lt;br&gt;
  }'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Savings: 30–60% on storage older than 90 days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. NAT Gateway Data Processing Charges&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What it costs: NAT Gateway charges $0.045 per GB processed; in both directions. Microservices calling each other through a NAT Gateway instead of VPC endpoints can generate $1,000+/month in charges that appear as "data transfer" on your bill.&lt;br&gt;
Why it happens: It's invisible. The architecture diagram looks fine. Nobody knows NAT Gateway charges per-GB until they see the bill.&lt;/p&gt;

&lt;p&gt;The fix — VPC endpoints for AWS services:&lt;/p&gt;

&lt;p&gt;`bash# Create a VPC endpoint for S3 (free — Gateway type)&lt;br&gt;
aws ec2 create-vpc-endpoint \&lt;br&gt;
  --vpc-id vpc-xxxxxxxxx \&lt;br&gt;
  --service-name com.amazonaws.eu-west-1.s3 \&lt;br&gt;
  --route-table-ids rtb-xxxxxxxxx&lt;/p&gt;

&lt;h1&gt;
  
  
  Create a VPC endpoint for DynamoDB (free — Gateway type)
&lt;/h1&gt;

&lt;p&gt;aws ec2 create-vpc-endpoint \&lt;br&gt;
  --vpc-id vpc-xxxxxxxxx \&lt;br&gt;
  --service-name com.amazonaws.eu-west-1.dynamodb \&lt;br&gt;
  --route-table-ids rtb-xxxxxxxxx`&lt;/p&gt;

&lt;p&gt;S3 and DynamoDB Gateway endpoints are free. Traffic to these services no longer routes through NAT Gateway.&lt;/p&gt;

&lt;p&gt;Savings: 10–30% of your NAT Gateway bill, potentially much more.&lt;/p&gt;

&lt;p&gt;How to Find All of This in 15 Minutes&lt;/p&gt;

&lt;p&gt;If you want to run through all five of these, plus 13 more checks across compute, storage, database, and networking, I built a free structured audit tool that does exactly this.&lt;/p&gt;

&lt;p&gt;No account access required. No IAM roles. No agents. You answer questions about your setup and it flags issues with savings estimates.&lt;/p&gt;

&lt;p&gt;kloudaudit.eu — free to run, takes 15 minutes.&lt;/p&gt;

&lt;p&gt;What's the biggest AWS cost surprise you've found on your bill? &lt;br&gt;
Drop it in the comments, always curious what patterns others are seeing.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to cut your AWS bill by 20–45% without touching your architecture</title>
      <dc:creator>KloudAudit</dc:creator>
      <pubDate>Mon, 27 Apr 2026 19:58:51 +0000</pubDate>
      <link>https://dev.to/kloudaudit/how-to-cut-your-aws-bill-by-20-45-without-touching-your-architecture-3b9j</link>
      <guid>https://dev.to/kloudaudit/how-to-cut-your-aws-bill-by-20-45-without-touching-your-architecture-3b9j</guid>
      <description>&lt;p&gt;Cloud bills grow quietly.&lt;br&gt;
You add a feature, spin up a database for testing, forget to delete it. You launch on On-Demand because you're moving fast. Your S3 bucket fills up and nobody sets lifecycle rules because "we'll do it later.&lt;br&gt;
Two years later you're paying $8,000/month and your CFO is asking questions.&lt;br&gt;
Here's a systematic way to audit your own bill in under an hour.&lt;br&gt;
Step 1 — Compute: find your zombies&lt;br&gt;
Pull a utilization report for the last 30 days. Any instance averaging under 10% CPU and 20% memory is a zombie. Either rightsize it or kill it. This alone typically saves 15–25% of compute spend.&lt;br&gt;
Step 2 — Reservations: stop paying on-demand tax&lt;br&gt;
If you've been running instances for 6+ months and they're stable, you're paying the most expensive rate possible. 1-year Reserved Instances or Compute Savings Plans cut this by 30–45% with zero architecture change.&lt;br&gt;
Step 3 — Storage: tier everything&lt;br&gt;
Data you haven't accessed in 90 days should not be in S3 Standard. Set lifecycle policies to move to Infrequent Access at 30 days, Glacier at 90 days. S3 Intelligent-Tiering does this automatically.&lt;br&gt;
Step 4 — Databases: dev environments&lt;br&gt;
Stop running your staging RDS 24/7. Use Lambda schedules to shut them down at 7pm and restart at 8am. That's 65% of the hours eliminated.&lt;br&gt;
Step 5 — Spot for batch&lt;br&gt;
Any workload that can tolerate interruption — CI runners, ML training, data pipelines — should be on Spot. 60–80% cheaper. AWS rarely reclaims Spot for most instance types.&lt;/p&gt;

&lt;p&gt;I built a free tool that walks you through all of this systematically — kloudaudit.eu. 18 checkpoints, takes 15 minutes, no account access needed.&lt;br&gt;
What am I missing? Drop your favorite cost-saving trick in the comments.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>tutorial</category>
      <category>security</category>
    </item>
  </channel>
</rss>
