Skip to content
All posts

Your Cloud Bill Is a Self-Inflicted Tax

April 28, 2026·Read on Medium·

Most small teams are running AWS workloads for problems they will never encounter.

Here is a pattern that plays out in small tech teams more often than it should. A developer joins the company, opens the infrastructure conversation with “we should probably be on AWS,” and nobody pushes back because AWS sounds responsible. Grown-up. Like the kind of decision a serious engineering team makes.

Eighteen months later, the monthly AWS bill is creeping toward $1,000 for a SaaS app with 300 active users. Nobody remembers why they picked AWS specifically. It just felt right at the time.

This is not about AWS being a bad product. It is not. AWS is genuinely excellent at what it does. The problem is that most small teams do not need what AWS does well, and they are paying a significant premium for capabilities they will never touch. Choosing AWS as a default is a failure of cost analysis, not a success of engineering judgment.

The Numbers That Do Not Get Compared Honestly

The conversation about cloud costs usually stays vague. “AWS is expensive but worth it.” Worth it compared to what? Let us be specific.

An AWS EC2 t3.medium instance (2 vCPU, 4 GB RAM) on-demand costs approximately $30.37 per month in us-east-1. The t3.large (2 vCPU, 8 GB RAM) runs $60.74 per month. These are compute-only prices. They do not include egress, storage, a managed database, a load balancer, or any of the other services you will need to actually run an application.

A Hetzner CX22 server (2 vCPU, 4 GB RAM) costs €3.79 per month. The CX32 (4 vCPU, 8 GB RAM) costs €6.80 per month. Both include 20 TB of monthly traffic.

A DigitalOcean Basic Droplet with 2 vCPU and 4 GB RAM costs $24 per month. Their 8 GB option runs $63 per month.

The Hetzner CX32 gives you more CPU, the same RAM and 20 TB of included traffic for roughly what AWS charges for one-eighth of the compute and almost none of the bandwidth. That is not a rounding error. That is a structural pricing difference that compounds across every service you add to your stack.

What AWS Charges for That Others Include

The compute difference is only part of the story. AWS’s real cost advantage over smaller providers has always been its breadth of managed services. But that advantage comes with a pricing model that punishes teams who are not deliberate about it.

AWS data egress costs $0.09 per GB for the first 10 TB per month after the 100 GB free tier. If your application serves any meaningful volume of data to clients or calls external APIs frequently, that line item appears on your bill and grows quietly. Hetzner includes 20 TB of outbound traffic in the base price of every server. DigitalOcean includes 4 TB with its $24 droplet.

Run the math for an application transferring 2 TB of data per month. On Hetzner, that is already included. On AWS, that is $170.10 in egress alone, on top of the compute charge.

This is before you add RDS for a managed database (a PostgreSQL db.t3.medium instance on RDS runs over $80 per month), an Application Load Balancer ($18 per month base plus LCU charges), or any CloudWatch logging that exceeds the free tier. A minimal production-grade AWS setup for a small application can easily reach $250 to $400 per month without anyone doing anything wrong. The costs are just the sum of the defaults.

On Hetzner, a comparable setup with a self-hosted PostgreSQL instance and Nginx as a reverse proxy lands well under $20 per month. You give up managed infrastructure for that price, which matters in specific situations. But for most small teams, the operational overhead of managing Postgres on a dedicated server is not the risk they imagine it to be.

When AWS Is Actually the Right Choice

There are legitimate reasons to choose AWS. The problem is that the actual use cases are narrower than the marketing implies.

If your product needs SOC 2 Type II or HIPAA compliance, AWS gives you the audit infrastructure, the BAAs and the compliance documentation that enterprise sales cycles demand. Hetzner does not. DigitalOcean has some of this, but AWS’s compliance coverage is deeper and more widely recognized. If you are selling to enterprise healthcare or financial services, the AWS premium is a business cost, not an engineering preference.

If your architecture requires geographic distribution across multiple regions with low-latency edge delivery, AWS CloudFront and its global infrastructure are genuinely hard to replicate. Hetzner operates primarily in Europe and the United States. If you need a presence in Southeast Asia, South America and the Middle East simultaneously, AWS is where that becomes straightforward.

If you have specific service dependencies with no viable alternative, that is a real constraint. Some teams are committed to SageMaker for ML pipelines, or Kinesis for high-throughput streaming, or Step Functions for complex workflow orchestration. These services have open-source analogues that require operational effort to run well. Whether that effort is worth avoiding the cost depends entirely on your team’s capacity and what else they are spending time on.

Beyond these situations, the case for AWS weakens quickly. A startup in the $0 to $1M ARR range usually has none of these requirements. A solo technical lead running a small product portfolio almost certainly does not.

What a Lean Production Stack Actually Looks Like

This is not theoretical. Small teams running production workloads have used this pattern, and it works.

Compute: Hetzner CX32 or CX42 for application servers. SSH access, Dokku or a simple Docker Compose setup for deploys. No Kubernetes unless you actually need it. A separate server for the database.

Database: Self-hosted PostgreSQL on a dedicated Hetzner instance with daily backups. Alternatively, Ubicloud offers managed PostgreSQL on Hetzner infrastructure at pricing that is substantially below AWS RDS. For teams that want fully managed without the AWS price tag, this is worth evaluating.

Object storage: Cloudflare R2. No egress charges. The pricing for storage is $0.015 per GB per month. For a small SaaS with a few hundred GB of user-generated content, the cost is negligible and the egress story is genuinely better than any alternative.

CDN and DDoS protection: Cloudflare free tier. DNS, SSL termination, HTTP/2, basic DDoS mitigation. This covers the network edge for most small applications without any additional cost.

Monitoring: A small VictoriaMetrics instance or Grafana Cloud free tier, with application metrics pushed via Prometheus exposition. This takes an afternoon to set up and handles monitoring for years without maintenance.

The configuration for a simple three-server setup (application, database, backup) on Hetzner plus Cloudflare R2 and Cloudflare DNS looks roughly like this:

Total monthly infrastructure cost:
- 2x Hetzner CX32 (app + db): €13.60
- 1x Hetzner CX22 (backup/cron): €3.79
- Cloudflare R2 (100 GB): ~$1.50
- Cloudflare (DDoS, CDN, DNS): $0

Total: ~€17.39 + $1.50/month

This stack handles a few hundred concurrent users without strain. It deploys via standard SSH and Docker. If you need to scale, you add servers. If you outgrow a single Postgres instance, you bring in read replicas or evaluate something like Neon for serverless Postgres at that point.

Compare this to a comparable AWS setup that would include an EC2 instance, RDS, S3 with CloudFront, Route 53 and a basic ALB. You are looking at $250 to $350 per month for similar capability.

The Migration You Are Putting Off

One common reason teams stay on AWS after they recognize the cost problem is inertia. The infrastructure is already there. Terraform state is already configured. S3 buckets have data in them. Moving feels like a project that nobody wants to own.

This fear is mostly disproportionate to the actual work involved. Migrating an application from AWS EC2 to Hetzner takes a day for a straightforward setup. Moving from S3 to Cloudflare R2 takes longer because of data transfer, but the migration tools are mature and R2 is S3-API compatible, which means most application code requires no changes.

The teams most stuck are the ones who have over-relied on AWS-specific services. If your application uses DynamoDB, Lambda at the edge, or SQS queues with Lambda consumers throughout, the migration cost is real. This is a separate argument for not building deep dependencies on provider-specific managed services from the start, but that ship may have already sailed.

For teams running EC2, RDS and S3, the actual migration work is often a weekend project for one person. The cost savings justify it within one or two months.

The Deeper Problem

The AWS-by-default pattern is not just a cost problem. It reflects a broader tendency to defer infrastructure decisions to brand recognition instead of analysis. AWS feels like the responsible choice because it is what large companies use. But large companies use AWS for reasons that do not apply to small teams: procurement relationships, compliance requirements, headcount to manage complexity and scale that justifies the pricing model.

A five-person team paying $800 per month for infrastructure that could cost $40 is not being responsible. It is being uncritical.

The fact that you could scale to 10 million users on AWS is not a reason to pay for that capability at 300 users. If you get to 10 million users, you will have the revenue to re-evaluate your infrastructure choices, and by then you will have a much clearer picture of what you actually need.

Right now, you almost certainly do not need it.

What to Do This Week

If you have not looked at your cloud bill in the last month, look at it today. Find the line items that make up the top 80% of the spend. Ask whether each one exists because your product requires it, or because it was the path of least resistance.

If you are pre-revenue or early-stage, there is no defense for a $400 cloud bill. Move to Hetzner, configure Cloudflare and put the savings toward something that compounds.

If you are post-revenue with compliance requirements or specific managed service dependencies, stay on AWS for those requirements. But strip everything else. Egress charges, over-provisioned instances, RDS for a database your smallest Hetzner server could handle and unused services from experiments you never cleaned up.

The cloud bill is not a fixed cost of running software. It is the accumulated result of decisions made without enough scrutiny. Most of those decisions are reversible.

Found this helpful?

If this article saved you time or solved a problem, consider supporting — it helps keep the writing going.

Originally published on Medium.

View on Medium
Your Cloud Bill Is a Self-Inflicted Tax — Hafiq Iqmal — Hafiq Iqmal