Irgendwann kommt bei jedem AWS-Nutzer der Moment: Die monatliche Rechnung liegt wieder höher als erwartet, und man weiß nicht genau, wofür. Das ist kein Versagen – das ist die Default-Situation. AWS macht es einfach, Ressourcen zu starten. Schwieriger ist es, den Überblick zu behalten.
Dieser Artikel zeigt 10 Maßnahmen, die sich in der Praxis bewährt haben – sortiert nach Aufwand und Sofortwirkung. Kein theoretisches FinOps-Framework, sondern konkrete Schritte, die du diese Woche umsetzen kannst.
Warum AWS-Rechnungen schneller wachsen als geplant
AWS hat über 200 Services. Viele davon rechnen sekundengenau ab, andere nach Datenmenge, wieder andere nach Anzahl der Anfragen. Die Komplexität des Preismodells ist kein Fehler – sie ist ein Feature für große Enterprise-Kunden. Für kleinere Teams bedeutet sie: Wer nicht aktiv schaut, zahlt zu viel.
Die häufigsten Kostentreiber, die ich in Projekten sehe:
- EC2-Instanzen, die rund um die Uhr laufen, obwohl sie nur tagsüber gebraucht werden
- EBS-Volumes, die nach dem Löschen einer Instanz vergessen wurden
- NAT Gateways mit unnötig hohem Datendurchsatz
- S3-Buckets mit Millionen kleiner Objekte und keiner Lifecycle-Policy
- RDS-Instanzen, die zu groß provisioniert sind und nie ausgelastet werden
- Snapshots, die seit Monaten niemand mehr braucht
Das Gute: Viele dieser Probleme lassen sich innerhalb weniger Stunden beheben. Fangen wir an.
1. Kostentransparenz herstellen: AWS Cost Explorer aktivieren
Bevor man optimiert, muss man wissen, wo das Geld hingeht. AWS Cost Explorer ist kostenlos und zeigt Ausgaben aufgeschlüsselt nach Service, Region, Tag und Zeitraum. Aktivieren kostet nichts, nicht aktivieren kostet Überblick.
Zwei Dinge, die ich sofort einrichte:
Cost Allocation Tags
Tags sind der Schlüssel zur Kostentransparenz. Ohne Tags weiß man nicht, welches Projekt oder Team welche Kosten verursacht. Im AWS Cost Management unter Cost Allocation Tags aktivieren:
# Alle EC2-Instanzen mit Projekt-Tag versehen (AWS CLI)
aws ec2 create-tags \
--resources i-1234567890abcdef0 \
--tags Key=Project,Value=myapp Key=Environment,Value=production Key=Owner,Value=emre
# Terraform-Beispiel: Tags auf alle Ressourcen setzen
locals {
common_tags = {
Project = var.project_name
Environment = var.environment
ManagedBy = "terraform"
Owner = var.owner
}
}
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux.id
instance_type = "t3.medium"
tags = local.common_tags
}
AWS Trusted Advisor
Mit einem Business- oder Enterprise-Support-Plan gibt Trusted Advisor konkrete Optimierungshinweise: ungenutzte EC2-Instanzen, idle Load Balancer, underutilized RDS. Für kleinere Konten liefert AWS Compute Optimizer ähnliche Empfehlungen kostenlos.
Sofortaktion: Cost Explorer aktivieren, die letzten 3 Monate analysieren, Top-5-Kostentreiber identifizieren. Das dauert 20 Minuten und zeigt, wo der größte Hebel liegt.
2. Ungenutzte Ressourcen eliminieren
Das ist die einfachste und schnellste Maßnahme – und gleichzeitig die, bei der die meisten Teams am meisten liegen lassen. Ungenutzte Ressourcen laufen still im Hintergrund und produzieren Kosten, ohne irgendeinen Wert zu liefern.
Checkliste für sofortige Bereinigung:
Gestoppte EC2-Instanzen & verwaiste EBS-Volumes
# Gestoppte Instanzen finden
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=stopped" \
--query "Reservations[*].Instances[*].[InstanceId,Tags[?Key=='Name'].Value|[0],LaunchTime]" \
--output table
# Ungenutzte EBS-Volumes (available = nicht attached)
aws ec2 describe-volumes \
--filters "Name=status,Values=available" \
--query "Volumes[*].[VolumeId,Size,CreateTime,Tags[?Key=='Name'].Value|[0]]" \
--output table
# Ungenutzte Elastic IPs (kosten Geld wenn nicht attached!)
aws ec2 describe-addresses \
--query "Addresses[?AssociationId==null].[PublicIp,AllocationId]" \
--output table
Alte Snapshots bereinigen
EBS-Snapshots kosten $0.05 pro GB und Monat. Klingt wenig – aber bei Hunderten von Snapshots über Jahre summiert sich das schnell auf dreistellige Monatsbeträge.
# Snapshots älter als 90 Tage im eigenen Account finden
aws ec2 describe-snapshots \
--owner-ids self \
--query "Snapshots[?StartTime<='2025-12-21'].[SnapshotId,VolumeSize,StartTime,Description]" \
--output table
Für automatisches Snapshot-Management empfehle ich AWS Data Lifecycle Manager – damit lassen sich Retention-Policies direkt in AWS definieren, ohne Cron-Jobs oder Lambda-Funktionen.
Brauchst du Unterstützung bei der Umsetzung?
30-Min Call — kostenlos, unverbindlich, konkret.
3. EC2 Right-Sizing: Instanzgröße an den echten Bedarf anpassen
Über-provisionierte EC2-Instanzen sind einer der größten Kostentreiber. Eine m5.xlarge kostet doppelt so viel wie eine m5.large – wenn die Auslastung nie über 20% liegt, zahlt man doppelt für nichts.
AWS Compute Optimizer analysiert CloudWatch-Metriken der letzten 14 Tage und gibt konkrete Empfehlungen. Alternativ: manuell über CloudWatch schauen.
# Durchschnittliche CPU-Auslastung der letzten 14 Tage
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
--start-time 2026-03-07T00:00:00Z \
--end-time 2026-03-21T00:00:00Z \
--period 86400 \
--statistics Average \
--query "Datapoints[*].[Timestamp,Average]" \
--output table
Faustregel: Wenn die durchschnittliche CPU-Auslastung unter 10% liegt und Spitzenwerte unter 40% bleiben, ist die Instanz überprovisioniert. Eine Größe kleiner (z.B. m5.large statt m5.xlarge) ist meist problemlos möglich.
Außerdem lohnt sich der Wechsel zur aktuellen Instanzgeneration: m5 → m7i oder m7g (Graviton) kann bei gleicher oder besserer Performance 20–30% günstiger sein.
| Instanztyp | vCPU | RAM | Preis/h (eu-central-1) | Ersparnis |
|---|---|---|---|---|
| m5.large | 2 | 8 GB | ~$0.107 | Basis |
| m7i.large | 2 | 8 GB | ~$0.109 | +15% Performance |
| m7g.large | 2 | 8 GB | ~$0.090 | −16% (Graviton) |
4. Reserved Instances: Rabatt durch Commitment
Wer EC2-Instanzen dauerhaft betreibt, sollte über Reserved Instances (RIs) oder Savings Plans nachdenken. Der Deal ist simpel: Du verpflichtest dich für 1 oder 3 Jahre, AWS gibt dir dafür 30–72% Rabatt.
Die Entscheidung hängt von der Nutzungssicherheit ab:
- Standard Reserved Instances (1 Jahr, no upfront): ~30–40% Ersparnis, kein Vorabkapital nötig
- Standard Reserved Instances (1 Jahr, all upfront): ~40–50% Ersparnis, Vorabzahlung
- Convertible RIs: Weniger Rabatt, aber flexibel in Instanztyp/Region wechselbar
Wann macht RI Sinn? Wenn eine Instanz seit >3 Monaten läuft und du sie mit hoher Wahrscheinlichkeit noch 12+ Monate brauchst. Nicht für Entwicklungsumgebungen, die gelegentlich abgeschaltet werden.
Praktisch: Im AWS Cost Explorer gibt es eine RI-Purchase-Empfehlung, die auf Basis der aktuellen Nutzung genau berechnet, welche RIs sich lohnen und wie hoch die Ersparnis wäre.
5. Spot Instances für unterbrechbare Workloads
Spot Instances sind ungenutzte EC2-Kapazitäten, die AWS mit bis zu 90% Rabatt anbietet – mit dem Haken, dass sie mit 2 Minuten Vorwarnung zurückgezogen werden können. Für die richtigen Workloads ist das ein enormer Hebel.
Geeignet für Spot Instances:
- CI/CD-Build-Jobs (Jenkins, GitHub Actions Self-Hosted Runner)
- Batch-Verarbeitung (Datenimporte, Berechnungen, Rendering)
- Entwicklungs- und Test-Umgebungen
- Stateless Web-Tier hinter einem Load Balancer (mehrere Instanzen)
- Machine-Learning-Training
Nicht geeignet:
- Datenbanken (zustandsbehaftet)
- Single-Point-of-Failure-Systeme ohne Redundanz
- Workloads mit strikten Latenz-SLAs
# Terraform: Spot Instance mit On-Demand-Fallback (Mixed Instances Policy)
resource "aws_autoscaling_group" "app" {
name = "app-asg"
vpc_zone_identifier = var.subnet_ids
min_size = 2
max_size = 10
desired_capacity = 3
mixed_instances_policy {
instances_distribution {
on_demand_base_capacity = 1 # Mindestens 1 On-Demand
on_demand_percentage_above_base_capacity = 20 # 20% On-Demand, 80% Spot
spot_allocation_strategy = "capacity-optimized"
}
launch_template {
launch_template_specification {
launch_template_id = aws_launch_template.app.id
version = "$Latest"
}
# Mehrere Instanztypen für höhere Spot-Verfügbarkeit
override {
instance_type = "m5.large"
}
override {
instance_type = "m5a.large"
}
override {
instance_type = "m6i.large"
}
}
}
}
6. S3 Lifecycle Policies: Alte Daten automatisch günstiger ablegen
S3 Standard kostet ca. $0.023 pro GB und Monat. S3 Glacier Instant Retrieval kostet $0.004 pro GB – also 83% weniger für Daten, die selten abgerufen werden. Mit Lifecycle Policies automatisiert AWS den Übergang.
{
"Rules": [
{
"ID": "move-old-logs-to-glacier",
"Status": "Enabled",
"Filter": { "Prefix": "logs/" },
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER_IR"
},
{
"Days": 365,
"StorageClass": "DEEP_ARCHIVE"
}
],
"Expiration": {
"Days": 730
}
}
]
}
S3 Intelligent-Tiering ist eine Alternative für Daten mit unvorhersehbarem Zugriffsmuster: AWS verschiebt Objekte automatisch zwischen Tiers, ohne dass du Zugriffszeiten kennen musst. Sinnvoll ab ~$0.0025 pro 1.000 Objekten Monitoring-Gebühr.
Weitere S3-Kostenfallen:
- Versionierung: Wenn aktiviert, sammeln sich alte Versionen an. Lifecycle Rule für nicht-aktuelle Versionen anlegen.
- Incomplete Multipart Uploads: Fehlgeschlagene Uploads belegen Speicher. Lifecycle Rule mit
AbortIncompleteMultipartUploadnach 7 Tagen. - Request-Kosten bei kleinen Objekten: Millionen kleiner Dateien (< 128 KB) machen S3 Intelligent-Tiering teuer. Kleine Objekte bündeln.
7. Data Transfer Costs im Griff behalten
Datentransfer ist oft der unsichtbarste Kostentreiber. Grob gesagt: eingehender Traffic ist kostenlos, ausgehender kostet. Und Traffic zwischen AWS-Services in verschiedenen Availability Zones oder Regionen kostet extra.
Häufige Fallen:
- NAT Gateway: Kostet $0.045 pro GB verarbeiteten Daten. Wenn EC2-Instanzen große Datenmengen über das NAT Gateway transferieren (z.B. S3-Zugriffe), summiert sich das schnell.
- Cross-AZ-Traffic: $0.01 pro GB in jede Richtung. Datenbank-Replikas in anderen AZs, Load Balancer – das zählt alles.
- CloudFront fehlt: Statische Assets direkt aus S3 ausliefern statt über CloudFront ist sowohl langsamer als auch teurer.
S3 Gateway Endpoint: NAT-Kosten bei S3-Zugriffen eliminieren
# Terraform: S3 Gateway Endpoint (kostenlos, kein NAT-Traffic mehr für S3)
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.eu-central-1.s3"
vpc_endpoint_type = "Gateway"
route_table_ids = aws_route_table.private[*].id
tags = {
Name = "s3-gateway-endpoint"
}
}
# DynamoDB-Endpoint ebenfalls kostenlos und empfehlenswert
resource "aws_vpc_endpoint" "dynamodb" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.eu-central-1.dynamodb"
vpc_endpoint_type = "Gateway"
route_table_ids = aws_route_table.private[*].id
}
Ein S3 Gateway Endpoint ist kostenlos und leitet den Datenverkehr von EC2 zu S3 direkt über das AWS-interne Netzwerk – das NAT Gateway wird dabei umgangen. Bei S3-intensiven Workloads kann das die Monatsbill deutlich reduzieren.
8. RDS optimieren: Größe, Storage und Aurora Serverless
RDS ist oft der zweitgrößte Kostenblock nach EC2. Drei Hebel mit sofortiger Wirkung:
Right-Sizing bei RDS
Gleiche Logik wie bei EC2: CloudWatch-Metriken (CPUUtilization, FreeableMemory, DatabaseConnections) anschauen. Eine db.r6g.xlarge statt db.r5.xlarge kann bei gleicher Performance 10–15% günstiger sein.
RDS Storage-Typ prüfen
gp2 (älterer Storage-Typ) kostet $0.138 pro GB. gp3 kostet $0.115 pro GB und ist 20% günstiger – mit konfigurierbarem IOPS ohne zusätzliche Kosten bis 3.000 IOPS. Migration von gp2 auf gp3 ist ein Klick in der Konsole, ohne Downtime.
# RDS-Instanzen mit gp2-Storage finden und auf gp3 migrieren
aws rds describe-db-instances \
--query "DBInstances[?StorageType=='gp2'].[DBInstanceIdentifier,AllocatedStorage,StorageType]" \
--output table
# Migration auf gp3 (apply immediately = kein Wartungsfenster nötig)
aws rds modify-db-instance \
--db-instance-identifier mydb \
--storage-type gp3 \
--apply-immediately
Aurora Serverless v2 für variable Workloads
Wenn Datenbankauslastung stark schwankt (nachts fast null, tagsüber Spitzen), ist Aurora Serverless v2 interessant: Die Kapazität skaliert in Sekunden von 0.5 bis 128 ACUs, und man zahlt nur für tatsächliche Nutzung. Für reine Dev-Datenbanken, die nachts nicht gebraucht werden, kann das 60–70% sparen.
9. Budget Alerts: Kosten-Explosionen frühzeitig erkennen
Alle Optimierungen nützen wenig, wenn beim nächsten Deployment aus Versehen 50 EC2-Instanzen gestartet werden und erst am Monatsende auffällt. AWS Budgets schickt Alarm, bevor das Budget überschritten wird.
# Terraform: Budget mit E-Mail-Alert bei 80% und 100% Threshold
resource "aws_budgets_budget" "monthly_cost" {
name = "monthly-cost-alert"
budget_type = "COST"
limit_amount = "500"
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 80
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["emre@example.com"]
}
notification {
comparison_operator = "GREATER_THAN"
threshold = 100
threshold_type = "PERCENTAGE"
notification_type = "FORECASTED" # Frühwarnung auf Basis von Trends!
subscriber_email_addresses = ["emre@example.com"]
}
}
# Anomalie-Erkennung: AWS meldet ungewöhnliche Kostenausreißer
resource "aws_ce_anomaly_monitor" "service" {
name = "AWSServiceCostAnomaly"
monitor_type = "DIMENSIONAL"
monitor_dimension = "SERVICE"
}
resource "aws_ce_anomaly_subscription" "realtime_alert" {
name = "realtime-anomaly-alert"
threshold = 20 # Alert wenn Anomalie > $20
frequency = "IMMEDIATE"
monitor_arn_list = [aws_ce_anomaly_monitor.service.arn]
subscriber {
type = "EMAIL"
address = "emre@example.com"
}
}
Die Anomaly Detection ist besonders wertvoll: Sie lernt das normale Ausgabemuster und schlägt Alarm, wenn ein Service plötzlich viel mehr kostet als üblich – auch wenn das Budget-Limit noch nicht erreicht ist.
10. Compute Savings Plans: Flexibler als Reserved Instances
Compute Savings Plans sind eine neuere Alternative zu Reserved Instances – mit einem entscheidenden Vorteil: Sie gelten für jeden EC2-Instanztyp, jede Region, Lambda und Fargate. Man committet sich auf einen stündlichen Ausgabebetrag (z.B. $2/h), nicht auf eine spezifische Instanzgröße.
Vergleich der Commitment-Modelle:
| Modell | Flexibilität | Ersparnis | Empfehlung |
|---|---|---|---|
| On-Demand | Maximum | 0% | Dev / volatile |
| Compute Savings Plan (1J) | Hoch | ~33% | Guter Einstieg |
| EC2 Instance SP (1J) | Mittel | ~40% | Wenn Instanzfamilie fix |
| Standard RI (3J, all upfront) | Gering | ~60–72% | Stabile, lange Planung |
Für die meisten Teams empfehle ich als Einstieg: Compute Savings Plan für 1 Jahr, no upfront. Kein Vorabkapital, ~33% Ersparnis, und man ist nicht an eine Instanzgröße gebunden. Erst wenn klar ist, welche Instanztypen langfristig stabil bleiben, lohnt sich der Wechsel zu spezifischeren (und günstigeren) Modellen.
Fazit: Prioritäten setzen, nicht alles auf einmal
10 Maßnahmen auf einmal umzusetzen ist unrealistisch. Die Empfehlung: Mit Transparenz starten, dann die Quick Wins mitnehmen, dann die strategischen Hebel angehen.
Sofort umsetzbar (diese Woche):
- Cost Explorer aktivieren, Top-Kostentreiber identifizieren
- Ungenutzte Ressourcen (EBS, EIPs, alte Snapshots) bereinigen
- S3 Gateway Endpoint einrichten (kostenlos, kein Aufwand)
- Budget Alerts und Anomaly Detection einrichten
Kurzfristig (nächste 2–4 Wochen):
- RDS gp2 → gp3 migrieren
- S3 Lifecycle Policies für Log-Buckets einrichten
- EC2 Right-Sizing auf Basis von CloudWatch-Daten
Strategisch (nächster Monat):
- Compute Savings Plan kaufen
- Spot Instances für CI/CD und Batch-Jobs einführen
- Data Transfer Costs analysieren und NAT Gateway-Optimierung
In meiner Erfahrung lassen sich bei den meisten AWS-Konten mit diesen Maßnahmen 20–40% der monatlichen Kosten einsparen – oft ohne eine einzige Zeile Anwendungscode anzufassen. Der größte Feind ist nicht mangelndes Wissen, sondern das Aufschieben des ersten Überblicks.
Wenn du wissen möchtest, wo bei deinem AWS-Setup die größten Hebel liegen, helfe ich gerne mit einem kurzen Review weiter. Schreib mich einfach an.