Skip to main content
Reducing Cloud Costs: 5 Simple Tweaks to Shrink Your AWS Bill
Photo by Growtika on Unsplash

Reducing Cloud Costs: 5 Simple Tweaks to Shrink Your AWS Bill

·7 mins·
AWS Cloud DevOps Cost-Optimization FinOps Tutorial
Table of Contents

Introduction
#

Using cloud infrastructure can sometimes feel almost like magic. A few clicks in the cloud console or a terraform apply in the terminal, and suddenly we have virtually unlimited resources at our disposal for our project. But at the end of the month, reality often sets in: the AWS bill is, once again, higher than expected.

It’s a classic scenario: you need a test instance for a quick PoC and then forget about it, or ancient backups pile up unnoticed in S3.

The good news is: you don’t have to completely overhaul your entire architecture or spend ages refactoring and optimising microservices to save money. Often, small, inconspicuous changes are enough – and together, they make a big difference.

With the following five simple quick wins, you can minimise your AWS bill (and those from any other cloud provider) straight away – without any headaches or downtime.


1. Skeletons in the cupboard: Orphaned EBS volumes & Elastic IPs
#

It is probably the most common cost driver in dev accounts: you delete an EC2 instance but overlook the tick box for “Delete on termination” on the EBS volume being used. The VM is gone, but the volume remains. It does nothing, but it sits on costly SSD storage and costs money unnecessarily every month.

The situation is similar with Elastic IPs (static IPv4 addresses). They are often overlooked during clean-up and incur costs even when they are not actively associated with a running instance. This is intended to prevent the hoarding of scarce IPv4 addresses.

How to clean them up:
#

  1. Open the EC2 Dashboard in the AWS Console.
  2. Click on Volumes and filter by the status State = available. Anything that appears here is not in use and can be deleted (you may want to take a snapshot beforehand, just to be on the safe side).
  3. Click on Elastic IPs and look for addresses that are not associated with an instance or a network interface. Select these and click on Release Elastic IP addresses.

Does this apply to other cloud platforms as well? Absolutely. Both Azure (Orphaned Disks) and GCP (Unattached IPs & Disks) charge you for unused storage and network resources. It’s definitely worth checking this section regularly.


2. The Easiest 20% Storage Discount: Upgrade gp2 to gp3
#

Are you still using gp2-type EBS volumes for your EC2 instances? If so, you’re giving AWS your money for no reason.

AWS introduced the new gp3 storage class some time ago. This offers significantly better value for money. Whilst with gp2 the performance (IOPS) is directly linked to the size of the volume (which often meant you had to rent volumes that were too large just to get more speed), with gp3 you can scale performance independently of capacity.

Best of all: gp3 is around 20 % cheaper than gp2 per gigabyte.

flowchart LR
    gp2["EBS gp2 (Legacy)"] -->|20% Savings & decoupled IOPS| gp3["EBS gp3 (Recommended)"]
    style gp2 fill:#f97316,stroke:#ea580c,color:#fff
    style gp3 fill:#10b981,stroke:#059669,color:#fff

How to upgrade:
#

You don’t even need to stop or restart the server to do this. The upgrade takes place whilst the server is running:

  1. Select the desired volume in the EC2 dashboard.
  2. Click Modify Volume.
  3. Change the type from gp2 to gp3.
  4. (Optional) Adjust the IOPS and throughput – the default values (3,000 IOPS, 125 MB/s) are usually already better than the old gp2 equivalent.
  5. Save. AWS migrates the data in the background whilst the server continues to run smoothly.

In Terraform, you only need to change a single line:

resource "aws_ebs_volume" "example" {
  availability_zone = "us-east-1a"
  size              = 100
- type              = "gp2"
+ type              = "gp3"
}

3. Dev Environments don’t have to be active all the time
#

Be honest: does your team work at 3 am or on a Sunday afternoon on the staging or development environment? In 99 % of cases, the answer is: no.

There are 720 hours in a month. If the dev instances only run during regular working hours (e.g. Monday to Friday, 8.00 am to 6.00 pm), they are only actually needed for around 200 hours per month. For the remaining 520 hours, they run completely for nothing. That’s a potential saving of over 70 %!

How to set it up:
#

AWS offers internal solutions such as the AWS Instance Scheduler, but often a simple automation using AWS Systems Manager (SSM) or a short Python script in an AWS Lambda function, triggered via Amazon EventBridge (Cron job), is sufficient.

A simple example of a Lambda script to stop EC2 instances with the tag Environment = Dev:

import boto3

ec2 = boto3.client('ec2', region_name='us-east-1')

def lambda_handler(event, context):
    # Find all running Dev instances
    # The tag-names are of course individual
    filters = [
        {'Name': 'tag:Environment', 'Values': ['dev']},
        {'Name': 'instance-state-name', 'Values': ['running']}
    ]
    
    instances = ec2.describe_instances(Filters=filters)
    instance_ids = []
    
    for reservation in instances['Reservations']:
        for instance in reservation['Instances']:
            instance_ids.append(instance['InstanceId'])
            
    if instance_ids:
        ec2.stop_instances(InstanceIds=instance_ids)
        print(f"Stopping instances: {instance_ids}")
    else:
        print("Did not find any running instances.")

Simply set up two EventBridge rules: the first triggers this script from Monday to Friday at 7.00 pm to stop the instances, and the second runs a corresponding start-up script at 7.30 am. This approach also works very well for managed databases such as Amazon RDS.


4. Help S3 Clean Up: Set Up Lifecycle Policies
#

Object storage such as Amazon S3 is quick to set up and cheap to run. So cheap, in fact, that it’s often tempting to just dump everything in there and never look at it again. Yet, over the course of months and years, terabytes of logs, temporary CSV exports and daily database backups accumulate.

Why pay the full price for backups from 2023 that may no longer be required by law to be retained, or that nobody needs anyway?

How to fix it:
#

Use S3 Lifecycle Rules. These allow you to define rules that automatically move objects to cheaper storage classes or permanently delete them after a certain period of time.

A lifecycle workflow for backups might look like this:

  • Days 0 to 30: S3 Standard (fast access for emergencies).
  • *From 30 days onwards: * Move to S3 Standard-IA (Infrequent Access) or S3 One Zone-IA. The storage cost is almost halved.
  • From 90 days: Move to the Amazon S3 Glacier Flexible Archive or Glacier Deep Archive (up to 95 % cheaper than S3 Standard).
  • After 1 year: Automatic deletion (provided compliance rules do not prevent this).

You can set up these rules in the AWS Console under the Management tab of the S3 bucket with just a few clicks.


5. The safetynet: AWS Budgets & Anomaly Detection
#

Every cloud user’s greatest fear is receiving an exorbitantly high bill at the end of the month because a bug has caused an infinite loop in a Lambda function, a Terraform definition has accidentally launched 100 instances instead of 10, or an API key has been leaked and crypto miners have taken over the AWS accounts.

If you don’t check the billing section until the 30th of the month, you’ve already lost. That’s what early warning systems are for.

Two free/low-cost tools to enable today:
#

  1. AWS Budgets: Create a simple budget for your expected monthly costs (e.g. 500 €). Set up alerts to trigger as soon as actual or forecast costs exceed 80 % and 100 % of this amount. You’ll receive an immediate email notification.
  2. AWS Cost Anomaly Detection: This tool uses traditional machine learning to analyse daily expenditure. If costs on a given day suddenly deviate from the normal pattern (e.g. because an S3 sync script has gone haywire), you’ll receive an immediate email or a message via Slack or Microsoft Teams. The AWS tool is completely free and can be set up in just two minutes.

Conclusion
#

Optimising cloud costs (or, as it’s now known, “FinOps”) doesn’t have to be a mammoth project. Start with the simple things: delete orphaned resources, switch to modern volume types such as gp3, shut down dev environments at night and at weekends, and protect yourself with anomaly detection.

Even these simple steps often reduce monthly costs significantly and give you the peace of mind to get back to your day-to-day business.

If you have any questions about implementation or need support with optimising your cloud infrastructure, please feel free to contact us via the channels listed below!

Timo Staudinger
Author
Timo Staudinger
Senior DevOps Engineer

Related

Terraform Remote Backends: Team Collaboration without State Problems
·4 mins
Terraform GitLab Hetzner DevOps Collaboration Tutorial
When working with Terraform in a team, remote backends are required. We show you how to set up the GitLab HTTP backend and Hetzner Object Storage.
uv: The Next Generation of Python Development
·5 mins
Python Uv Package Manager DevOps Tools How-To
Introduction to the Python package manager uv. How does it work? In which areas can it be used? And the comparison with established tools like pip and venv.
CI/CD in Practice
·5 mins
DevOps CI-CD GitLab GitHub Actions Automation
A brief overview of what to consider with CI/CD and how to implement it successfully