
Your AWS Bill Is Too High โ Hereโs How FinOps Fixes It
๐ ๐ผ๐๐ ๐ฐ๐น๐ผ๐๐ฑ ๐ฒ๐ป๐ด๐ถ๐ป๐ฒ๐ฒ๐ฟ๐ ๐ณ๐ผ๐ฐ๐๐ ๐ผ๐ป ๐ฏ๐๐ถ๐น๐ฑ๐ถ๐ป๐ด. ๐ก๐ผ๐ฏ๐ผ๐ฑ๐ ๐๐ฎ๐น๐ธ๐ ๐ฎ๐ฏ๐ผ๐๐ ๐๐ต๐ฒ ๐ฏ๐ถ๐น๐น. ๐จ๐ป๐๐ถ๐น ๐ถ๐'๐ ๐๐ผ๐ผ ๐น๐ฎ๐๐ฒ. ๐๐ถ๐ป๐ข๐ฝ๐ is the practice of making every team responsible for their AWS spending โ ๐ฒ๐ป๐ด๐ถ๐ป๐ฒ๐ฒ๐ฟ๐ถ๐ป๐ด, ๐ณ๐ถ๐ป๐ฎ๐ป๐ฐ๐ฒ, ๐ฎ๐ป๐ฑ ๐ผ๐ฝ๐ ๐๐ผ๐ด๐ฒ๐๐ต๐ฒ๐ฟ.
A practical guide for developers, DevOps engineers, and cloud architects on optimizing AWS costs without sacrificing performance.
1. Introduction to FinOps on AWS
FinOps (Cloud Financial Operations) is the practice of bringing financial accountability to the variable spend model of cloud. It's not just about cutting costs โ it's about making sure every dollar spent on AWS delivers real value.
The problem? AWS makes it easy to spin up resources and hard to track what they cost. A startup can go from $500/month to $5,000/month overnight โ not because they grew, but because someone forgot to delete a NAT Gateway.
The FinOps triangle: Engineering + Finance + Operations
All three teams share responsibility:
- Engineering decides what to build and how
- Finance tracks budgets and forecasts
- Operations monitors usage and waste
Without all three aligned, cloud bills spiral out of control.
Why AWS costs are hard to control:
- 200+ services, each with unique pricing models
- Data transfer costs hidden between services
- Resources auto-provisioned by managed services
- No hard spending limits by default
2. Understanding AWS Pricing Models
Choosing the wrong pricing model is one of the fastest ways to overspend.
Pay-As-You-Go (On-Demand)
The default. You pay for what you use, when you use it. Great for unpredictable workloads. Expensive for steady-state production systems.
Best for: Dev/test environments, unpredictable spikes, new workloads
Savings Plans
Commit to a consistent amount of compute usage ($/hour) for 1 or 3 years. Get up to 66% discount vs on-demand.
Two types:
- Compute Savings Plans โ apply to EC2, Lambda, Fargate across any region/instance family
- EC2 Instance Savings Plans โ deeper discount but locked to specific instance family + region
Best for: Stable production workloads with predictable usage
Reserved Instances (RIs)
Commit to a specific instance type in a specific region for 1 or 3 years. Up to 72% discount.
Best for: Databases (RDS), steady EC2 workloads, when you know exactly what you need
Spot Instances
Use AWS's spare EC2 capacity at up to 90% discount. Can be interrupted with 2-minute notice.
Best for: Batch processing, ML training, fault-tolerant workloads, Kubernetes worker nodes
Pricing Model Comparison Table
Model Discount Commitment Best Use Case On-Demand 0% None Dev/test, spikes Savings Plans Up to 66% 1-3 years Stable compute Reserved Instances Up to 72% 1-3 years Databases, steady EC2 Spot Instances Up to 90% None Batch, ML, fault-tolerant Free Tier 100% 12 months Learning, prototypes
Data Transfer Pricing โ The Hidden Cost
This is where most teams get surprised:
- Data IN to AWS: Free
- Data OUT to internet: $0.09/GB (first 10TB/month)
- Between AZs in same region: $0.01/GB each way
- Between regions: $0.02โ$0.09/GB depending on regions
A microservices architecture with 10 services talking across AZs can generate thousands of dollars in transfer costs alone.
3. AWS Cost Analysis by Service Category
Compute Services
Amazon EC2
Pricing factors:
- Instance type (CPU, RAM, GPU)
- Region
- Operating system
- Data transfer
- EBS storage attached
Common mistakes:
- Running oversized instances "just in case"
- Leaving instances running 24/7 for dev/test
- Ignoring CPU credits on T-series instances (T3 unlimited mode charges extra)
Optimization:
- Use AWS Compute Optimizer to right-size instances
- Schedule non-production instances to stop nights/weekends (saves ~65%)
- Use Auto Scaling instead of always-on large instances
EC2 vs Lambda comparison:
EC2 Lambda Billing Per hour (minimum) Per 100ms + requests Cold starts No Yes (100msโ2s) Best for Long-running processes Event-driven, short tasks Max duration Unlimited 15 minutes Scaling Manual/Auto Scaling Automatic
AWS Lambda
Hidden costs:
- Memory allocation affects both price AND duration
- Provisioned concurrency charges even when idle
- Data transfer out still applies
Optimization:
- Right-size memory (use AWS Lambda Power Tuning tool)
- Avoid provisioned concurrency unless you have strict latency SLAs
- Use ARM/Graviton2 runtime โ 20% cheaper, often faster
ECS vs EKS
ECS EKS Control plane cost Free $0.10/hour (~$73/month) Complexity Lower Higher Flexibility AWS-native Kubernetes-native Best for AWS-first teams Multi-cloud, large orgs
Fargate vs EC2-backed containers:
Fargate is 35โ50% more expensive per vCPU/GB than EC2-backed. But it eliminates node management overhead. For small teams: Fargate wins on total cost (time included). For large scale: EC2 node groups with Spot wins on raw cost.
Storage Services
Amazon S3
S3 costs come from four places most people miss:
- Storage โ charged per GB per month by storage class
- Requests โ GET, PUT, LIST all cost money
- Data retrieval โ Glacier charges for retrieval
- Replication โ cross-region replication doubles storage cost
S3 Storage Classes:
Class Use Case Cost (approx) S3 Standard Frequently accessed $0.023/GB S3-IA Infrequent access $0.0125/GB S3 Glacier Instant Archives, ms retrieval $0.004/GB S3 Glacier Deep Archive Long-term archives $0.00099/GB
Optimization:
- Enable S3 Intelligent-Tiering for unpredictable access patterns (auto-moves objects between tiers)
- Set lifecycle policies: Standard โ IA after 30 days โ Glacier after 90 days
- Enable S3 Storage Lens to identify unused buckets and request patterns
- Delete incomplete multipart uploads (they accumulate silently)
How versioning increases costs: Every version of every object is stored and billed. A 1MB file updated daily for a year = 365MB billed. Add a lifecycle policy to expire old versions.
Amazon EBS
Hidden cost: Snapshots are charged even after the volume is deleted if you forget to clean them up.
Optimization:
- Delete unattached volumes immediately (use AWS Config rule: ec2-volume-inuse-check)
- Use gp3 instead of gp2 โ same performance, 20% cheaper, and IOPS/throughput are configurable independently
- Set Data Lifecycle Manager to auto-delete snapshots older than N days
Database Services
RDS vs Aurora
RDS Aurora Cost Lower base cost 20% more than RDS Performance Standard Up to 5x MySQL, 3x PostgreSQL Scaling Manual Auto-scales storage Best for Simple apps, tight budgets High-traffic production
Hidden RDS costs:
- Multi-AZ doubles instance cost
- Read replicas are billed as full instances
- Automated backups stored beyond retention window charge extra
- IOPS on io1 volumes are expensive โ consider gp3 for most workloads
DynamoDB
Provisioned vs On-Demand:
Provisioned On-Demand Cost Lower (predictable traffic) Higher per request Risk Over/under-provision No capacity planning Best for Stable, predictable load Spiky or unknown traffic
Optimization: Use DynamoDB Reserved Capacity for provisioned mode. Up to 76% discount on read/write capacity units with 1-year commitment.
Networking Costs
NAT Gateway โ The Quiet Bill Killer
NAT Gateway charges:
- $0.045/hour per gateway (~$32/month just to exist)
- $0.045/GB of data processed
An application sending 1TB/month through NAT Gateway = $45 in data processing + $32 base = $77/month per AZ.
Alternatives:
- Use VPC Endpoints for S3 and DynamoDB โ free, bypasses NAT Gateway entirely
- Use Interface Endpoints for other AWS services โ cheaper than NAT for high-volume
- For EC2 instances only accessing AWS services: remove NAT, use endpoints
CloudFront vs Direct S3/EC2
CloudFront data transfer OUT costs less than direct EC2 data transfer after 10TB/month. For public-facing apps serving media or static assets, CloudFront almost always reduces costs AND improves performance.
Public IP Charges
Since February 2024, AWS charges $0.005/hour (~$3.65/month) for every public IPv4 address, even if unused. Audit your Elastic IPs immediately โ any unattached EIP is pure waste.
Monitoring & Logging
CloudWatch Cost Traps
- Custom metrics: $0.30/metric/month. A microservices app publishing 100 custom metrics = $30/month
- Log ingestion: $0.50/GB. Verbose application logs can easily hit hundreds of GB/month
- Log storage: $0.03/GB/month. Logs retained forever compound over time
Optimization:
- Set log retention policies (14-30 days for most, 90 days for security/compliance)
- Use CloudWatch Logs Insights only when needed โ queries are charged per GB scanned
- Filter logs at the application level before sending to CloudWatch
- Use EMF (Embedded Metric Format) to batch custom metrics efficiently
Security Services โ Cost vs Protection Tradeoffs
Service Cost What You Get GuardDuty ~$4/million events Threat detection (enable always) Security Hub $0.001/finding Unified compliance dashboard AWS Config $0.003/config item Resource change tracking WAF $5/WebACL + $1/rule/month Web application firewall Shield Standard Free Basic DDoS protection Shield Advanced $3,000/month Enterprise DDoS + 24/7 response
Recommendation: GuardDuty + Security Hub are non-negotiable for any production account. WAF is essential for public-facing APIs. Shield Advanced only if you're a high-profile target.
4. Identifying AWS Cost Leaks
These are the most common sources of silent waste:
Zombie Resources Checklist
Resource How to Find Monthly Cost Unattached EBS volumes EC2 Console โ Volumes โ filter "available" $0.08-0.10/GB Unattached Elastic IPs EC2 Console โ Elastic IPs $3.65/IP Idle RDS instances CloudWatch โ DatabaseConnections < 1 for 7 days Full instance cost Unused Load Balancers ELB Console โ check RequestCount = 0 $16-22/month Old snapshots EC2 โ Snapshots โ sort by date $0.05/GB Stopped EC2 instances EC2 Console โ filter "stopped" (EBS still charged) EBS cost Idle NAT Gateways VPC Console โ NAT Gateways $32+/month
How to Detect Automatically
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Find all unattached EBS volumes
aws ec2 describe-volumes \
--filters Name=status,Values=available \
--query 'Volumes[*].{ID:VolumeId,Size:Size,AZ:AvailabilityZone}' \
--output table
# Find unassociated Elastic IPs
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].{IP:PublicIp,AllocationId:AllocationId}' \
--output table
# Find RDS instances with zero connections (last 7 days)
aws cloudwatch get-metric-statistics \
--namespace AWS/RDS \
--metric-name DatabaseConnections \
--statistics Average \
--period 604800 \
--start-time $(date -d '7 days ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date +%Y-%m-%dT%H:%M:%S) 5. AWS Cost Optimization Tools
AWS Cost Explorer
Your first stop. Visualizes spending by service, region, account, and tag. Use it to:
- Identify top 5 cost drivers
- Spot month-over-month anomalies
- Get Reserved Instance recommendations
AWS Budgets
Set spending alerts before you overspend โ not after. Configure:
- Monthly cost budget with 80% and 100% alerts
- Service-specific budgets (e.g., EC2 budget: $500/month)
- Forecast-based alerts ("you're on track to exceed budget")
AWS Compute Optimizer
Analyzes EC2, Lambda, EBS, ECS usage patterns and recommends right-sizing. Can identify instances that are 2-4x over-provisioned. Enable it โ it's free for basic recommendations.
Trusted Advisor
Flags low-hanging fruit automatically:
- Underutilized EC2 instances
- Idle load balancers
- Unassociated Elastic IPs
- S3 buckets with open access
Cost and Usage Reports (CUR)
The most granular cost data AWS provides. Export to S3, query with Athena, build dashboards in QuickSight. Essential for enterprise cost allocation and chargeback.
6. FinOps for Kubernetes on AWS (EKS)
EKS cost structure:
- Control plane: $0.10/hour ($73/month) per cluster
- Worker nodes: EC2 or Fargate pricing
- Data transfer: Between pods across AZs
Optimization Strategies
Use Spot node groups for non-critical workloads:
1
2
3
4
5
6
7
8
9
# eksctl node group with Spot instances
nodeGroups:
- name: spot-workers
instancesDistribution:
maxPrice: 0.05
instanceTypes: ["m5.large", "m5a.large", "m4.large"]
onDemandBaseCapacity: 0
onDemandPercentageAboveBaseCapacity: 0
spotAllocationStrategy: capacity-optimized Use Karpenter instead of Cluster Autoscaler: Karpenter provisions exactly the right instance type for pending pods in seconds, rather than scaling pre-defined node groups. Can reduce node waste by 20-40%.
Set resource requests and limits on every pod:
1
2
3
4
5
6
7
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m" Without requests, the scheduler can't bin-pack efficiently โ you end up with half-empty nodes running at full cost.
Namespace-level cost tracking: Use tools like Kubecost or OpenCost to allocate EKS costs by namespace, team, or application.
7. FinOps Automation
Auto-Shutdown Non-Production Resources
Lambda function to stop EC2 instances outside business hours:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import boto3
import json
ec2 = boto3.client('ec2')
def lambda_handler(event, context):
# Find all instances tagged Environment=dev
response = ec2.describe_instances(
Filters=[
{'Name': 'tag:Environment', 'Values': ['dev', 'staging']},
{'Name': 'instance-state-name', 'Values': ['running']}
]
)
instance_ids = []
for reservation in response['Reservations']:
for instance in reservation['Instances']:
instance_ids.append(instance['InstanceId'])
if instance_ids:
ec2.stop_instances(InstanceIds=instance_ids)
print(f"Stopped {len(instance_ids)} dev/staging instances")
return {'stopped': instance_ids} Schedule with EventBridge: Stop at 8pm, start at 8am weekdays. Saves ~65% on dev instance costs.
Terraform Cost Policy with Sentinel
1
2
3
4
5
6
7
8
9
10
11
12
13
# Deny expensive instance types in non-production
policy "restrict-instance-types" {
enforcement_level = "hard-mandatory"
}
main = rule {
all tfplan.resources.aws_instance as _, instances {
all instances as _, r {
r.applied.instance_type not in ["p3.16xlarge", "x1e.32xlarge"]
or r.applied.tags["Environment"] is "production"
}
}
} 8. Governance & Best Practices
Tagging Strategy โ The Foundation of FinOps
Without tags, you can't allocate costs to teams, projects, or environments. Define a mandatory tag schema:
1
2
3
4
5
Environment: production | staging | dev
Team: security | platform | data | frontend
Project: guardian | unmask | internal
CostCenter: eng-001 | ops-002
Owner: disha@company.com Use AWS Config rule required-tags to enforce tagging on all resources.
Multi-Account Architecture
Account Purpose Cost Isolation Management Billing, Organizations No workloads Production Live customer workloads Strict budgets Staging Pre-production testing Moderate budgets Dev Developer sandboxes Hard spending limits Security GuardDuty, Security Hub, logs Centralized
Use AWS Organizations + SCPs to enforce guardrails across accounts (e.g., block expensive regions, require encryption).
Startup FinOps Model
- Enable Cost Explorer + Budgets immediately
- Use Free Tier aggressively for first 12 months
- Tag everything from day one
- Use Spot for all non-production
- Review bill weekly, not monthly
Enterprise FinOps Model
- Dedicated FinOps engineer or team
- Cost allocation via CUR + Athena + QuickSight
- Chargeback to business units monthly
- Savings Plans + RIs covering 70%+ of steady-state
- Automated anomaly detection with CloudWatch + SNS
9. Real-World Case Studies
Case 1: Startup Reduces AWS Bill by 70%
Before: $8,000/month
- 20 EC2 instances (all on-demand, all running 24/7)
- 5 RDS instances (Multi-AZ everywhere, including dev)
- No S3 lifecycle policies
- NAT Gateway processing 2TB/month
After: $2,400/month
- EC2: Moved to Savings Plans + Spot for batch jobs โ saved $2,800
- RDS: Single-AZ for dev/staging, reserved 1-year for production โ saved $1,200
- S3: Intelligent-Tiering + Glacier lifecycle โ saved $400
- NAT: Replaced with VPC endpoints for S3/DynamoDB โ saved $400
- Dev instances shut down nights/weekends โ saved $800
Case 2: Replacing NAT Gateway Architecture
Before:
1
2
Private EC2 โ NAT Gateway โ Internet โ S3/DynamoDB
Cost: $32/month base + $45/TB data processed After:
1
2
Private EC2 โ VPC Endpoint โ S3/DynamoDB (AWS backbone, no internet)
Cost: $0 for S3 endpoint, $0.01/GB for interface endpoints Monthly saving for 1TB workload: $77 โ $10
Case 3: S3 Lifecycle Optimization
A security platform storing CloudTrail logs: 50TB total, 48TB never accessed after 30 days.
Before: 50TB ร $0.023 = $1,150/month After: 2TB Standard + 48TB Glacier Deep Archive = $46 + $47.5 = $93.5/month Saving: $1,056/month
10. Expensive Services vs Smarter Alternatives
Not every AWS managed service is worth the price tag. Here's when to use the premium option โ and when a cheaper alternative does the same job.
See content credentials
Decision Framework: When to Pay Premium
Ask these three questions before choosing the expensive option:
- Is this production? Dev/staging almost never needs premium services
- Is there a compliance requirement? If yes, the premium service may be mandatory (CloudHSM, Secrets Manager)
- Does the alternative hit your SLA? If the cheaper option meets your latency/availability needs, use it
Rule of thumb: Start with the cheaper alternative. Upgrade only when you hit a real, measurable limitation.
11. Common AWS FinOps Mistakes
Overengineering for scale you don't have yet Multi-AZ, read replicas, and auto-scaling on a 100-user app is expensive and unnecessary. Build for current scale, architect for future scale.
Ignoring data transfer costs Engineers focus on compute and storage. Data transfer between services, AZs, and regions silently adds 15-30% to bills.
Keeping everything "highly available" Multi-AZ RDS for a dev database costs 2x. Single-AZ with daily snapshot is fine for non-production.
No tagging strategy from day one Retroactively tagging 200 resources across 5 accounts is painful. Tag at resource creation, enforce with AWS Config.
Not using Spot instances Spot is 90% cheaper for interruptible workloads. Most batch jobs, ML training, and CI/CD pipelines can tolerate interruption with proper design.
Forgetting SageMaker notebook instances A ml.m5.xlarge notebook left running costs $120/month. Idle SageMaker endpoints are similarly expensive. Auto-shutdown notebooks after 1 hour of inactivity.
12. Future of FinOps on AWS
AI-driven cost optimization: AWS is integrating ML into Cost Explorer to predict spend and proactively recommend optimizations before waste happens.
Predictive scaling: Instead of reactive Auto Scaling, predictive scaling uses ML to provision capacity before demand spikes โ avoiding both over-provisioning and performance degradation.
GreenOps: AWS now provides carbon footprint dashboards per service and region. Sustainable architecture and cost-efficient architecture increasingly overlap โ fewer running resources means lower cost AND lower emissions.
FinOps as code: Teams are moving toward defining cost budgets and policies in code (Terraform, CDK), reviewed in pull requests alongside infrastructure changes. Cost becomes a first-class engineering concern, not an afterthought.
Cost Optimization Checklist
Immediate (do this week)
- [ ] Enable AWS Cost Explorer
- [ ] Set up Budget alerts (80% and 100%)
- [ ] Audit unattached EBS volumes and Elastic IPs
- [ ] Check for unused NAT Gateways
- [ ] Enable GuardDuty and Security Hub
Short-term (this month)
- [ ] Implement mandatory tagging policy
- [ ] Switch EBS volumes from gp2 to gp3
- [ ] Add S3 lifecycle policies to all buckets
- [ ] Enable Compute Optimizer
- [ ] Schedule dev/staging instance shutdown
Long-term (this quarter)
- [ ] Evaluate Savings Plans for steady-state workloads
- [ ] Replace NAT Gateway with VPC endpoints where possible
- [ ] Implement Karpenter for EKS cost optimization
- [ ] Set up CUR + Athena for detailed cost analysis
- [ ] Build FinOps dashboard in QuickSight or Grafana
This article is part of the Explore AWS series โ 100 AWS services, 100 days, one cloud security lens.
Follow along on LinkedIn
#AWS #FinOps #CloudCost #CloudSecurity #DevSecOps #AWSCommunityBuilders #Devops #devsecops #cybersecurity #Developers
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article