What FinOps/cost optimization solutions would you implement in cloud infrastructure?

What FinOps/cost optimization solutions would you implement in cloud infrastructure?

How to reduce your AWS bill by 30-60% without sacrificing performance or reliability.


Introduction

Cloud bills grow silently. A team provisions a large RDS instance “just in case,” dev environments run 24/7 when developers work 8 hours, and nobody notices the NAT Gateway quietly charging $0.045/GB on every outbound byte.

FinOps (Financial Operations) isn’t about cutting corners — it’s about spending wisely. The goal: every pound spent on infrastructure delivers business value. Idle resources, over-provisioned instances, and unused storage are waste — not safety.

In this post, I’ll walk through practical cost optimization strategies across Compute, Networking, Databases, and Storage — with real numbers and tools you can implement today.


The FinOps Mindset

Before diving into tactics, here’s the principle:

“Cost optimization is a continuous practice, not a one-time project. And the number one rule: never compromise security or reliability to save money.

The approach:

  1. Identify — where is the money going? (visibility)
  2. Optimize — right-size, schedule, choose the right pricing model
  3. Automate — scale down when not needed, eliminate waste automatically
  4. Govern — prevent runaway spending before it happens

Compute Optimization (EKS / ECS / EC2)

Compute is typically 60-70% of your AWS bill. This is where the biggest savings live.

Right-Size Your Instances

Most EC2 instances and Kubernetes pods are over-provisioned. Teams provision for peak load and then never revisit.

How to identify waste:

  • AWS Compute Optimizer — free, analyses 14 days of CloudWatch metrics, recommends smaller instance types
  • Datadog resource metrics — check actual CPU/memory usage vs requested/limits
  • kubectl top pods — see real utilisation vs what’s allocated

Example savings:

Before: m5.xlarge (4 vCPU, 16 GB) running at 15% CPU, 30% memory
After:  m5.large  (2 vCPU, 8 GB)  running at 30% CPU, 60% memory
Savings: 50% on that instance (~$70/month per instance)

Use Spot Instances for Non-Critical Workloads

Workload Spot Suitable? Savings
CI/CD runners (GitLab) Yes — jobs are short, retryable 60-90%
Dev/test environments Yes — interruption acceptable 60-90%
Batch processing Yes — checkpointable 60-90%
Production APIs No — use Savings Plans instead
Stateful databases No — data integrity risk

Best practice for Spot:

  • Request 6+ instance types (don’t depend on one type)
  • Use capacity-optimized allocation strategy
  • Fall back to On-Demand if no Spot available
  • Handle the 2-minute interruption warning gracefully

Savings Plans / Reserved Instances for Stable Workloads

Commitment Discount Best For
No commitment (On-Demand) 0% Unpredictable, short-term
1-year Savings Plan (no upfront) 20-30% Production workloads you’ll run for a year
1-year Savings Plan (all upfront) 30-40% Stable production, budget available
3-year Savings Plan (all upfront) 50-60% Long-term committed infrastructure

Tip: Start with Compute Savings Plans (flexible across instance families) rather than EC2 Reserved Instances (locked to specific type).

Karpenter for EKS (Automatic Node Right-Sizing)

“Karpenter is the single biggest EKS cost optimization tool. It replaces Cluster Autoscaler and makes better decisions.”

What Karpenter does:

  • Picks the cheapest instance type that fits your pod requirements
  • Consolidates pods onto fewer nodes (removes empty/underused nodes)
  • Supports Spot + On-Demand mixed strategies
  • Launches new nodes in 30 seconds (vs 4-5 minutes for Cluster Autoscaler)

Real impact: At our organisation, Karpenter reduced EKS compute costs by ~30% by consolidating workloads and choosing optimal instance types automatically.

Schedule Non-Production Environments

Dev and staging environments running 24/7 waste 65% of their cost (only used ~50 hours/week out of 168).

Implementation with kube-downscaler:

# Scale to zero pods outside business hours
metadata:
  annotations:
    downscaler/downtime: "Mon-Fri 19:00-07:00 Europe/London,Sat-Sun 00:00-24:00 Europe/London"

Savings calculation:

10 proxy services × 2 pods each × m6g.large ($0.077/hr)
Running 24/7:  $0.077 × 20 pods × 730 hours = $1,124/month
Running 50hrs: $0.077 × 20 pods × 217 hours = $334/month
Savings: $790/month (70% reduction)

Networking Optimization

Networking costs are the silent killer — they don’t appear as a clear line item and grow with traffic.

VPC Endpoints (Biggest Quick Win)

Traffic Type Without Endpoint With Endpoint Savings
S3 access NAT GW: $0.045/GB processing + data transfer Gateway endpoint: FREE 100%
ECR image pulls NAT GW: $0.045/GB Interface endpoint: $7.20/month flat Huge for image-heavy clusters
Secrets Manager NAT GW per call Interface endpoint: flat fee Significant for frequent secret fetches

Rule: If a service talks to S3 or DynamoDB, ALWAYS use a Gateway endpoint. It’s free and eliminates NAT charges for that traffic.

NAT Gateway Per AZ

Problem: A single NAT Gateway in one AZ means ALL other AZs send traffic cross-AZ ($0.01/GB each way) just to reach the NAT.

Fix: Deploy one NAT Gateway per AZ with AZ-specific route tables.

Cost of 3 NAT Gateways: 3 × $0.045/hr = $97/month
Cross-AZ savings for a busy cluster: $200-500/month
Net savings: $100-400/month

CloudFront Caching

  • Cache static assets at the edge — reduces origin requests (and data transfer)
  • Set appropriate TTLs (CSS/JS: 1 year with cache-busting, API: seconds/minutes)
  • Use Origin Shield to reduce origin load further

Reduce Cross-AZ Traffic

  • Enable Kubernetes Topology Aware Routing (pods prefer same-AZ endpoints)
  • Keep chatty service pairs in the same AZ using pod affinity
  • Use GIT_DEPTH: 1 in CI/CD to reduce clone data transfer

Database Optimization (RDS / DynamoDB / Aurora)

Right-Size Your Database

“Most production databases are over-provisioned. Check CloudWatch: if CPU averages 20% and max is 40%, you can safely downsize.”

Before: db.r6g.xlarge (4 vCPU, 32 GB) — $0.48/hr = $350/month
After:  db.r6g.large  (2 vCPU, 16 GB) — $0.24/hr = $175/month
Savings: $175/month per instance

Aurora Serverless v2 (Pay Per Use)

For databases with variable traffic — busy during the day, idle at night — Aurora Serverless scales down to 0.5 ACU when idle.

Traditional RDS (always on):  db.r6g.large × 730 hours = $175/month
Aurora Serverless (variable):  0.5 ACU × 12 hrs/night + 4 ACU × 12 hrs/day = ~$95/month
Savings: ~45%

Stop Dev/Test Databases Outside Business Hours

# Lambda + EventBridge: stop at 7pm, start at 8am
aws rds stop-db-instance --db-instance-identifier dev-booking-db
# RDS auto-starts after 7 days — use a Lambda to re-stop it

Savings: 60% for databases only used during business hours.

DynamoDB: On-Demand vs Provisioned

Traffic Pattern Best Mode Why
Unpredictable spikes On-Demand Pay per request, no capacity planning
Steady, predictable Provisioned + Auto-scaling 5-7x cheaper than On-Demand at steady load
Occasional (< 1 req/sec) On-Demand Provisioned minimum is wasteful for low traffic

Use Read Replicas Instead of Scaling Up

Instead of doubling your primary DB size for read-heavy workloads, add a read replica (50% the cost of scaling the primary).


Storage Optimization (S3 / EBS / EFS)

S3 Lifecycle Policies (Set and Forget)

{
  "Rules": [
    {
      "ID": "OptimizeLogStorage",
      "Status": "Enabled",
      "Transitions": [
        { "Days": 30, "StorageClass": "STANDARD_IA" },
        { "Days": 90, "StorageClass": "GLACIER" },
        { "Days": 365, "StorageClass": "DEEP_ARCHIVE" }
      ],
      "Expiration": { "Days": 730 }
    }
  ]
}

Savings example:

100 TB of logs in S3 Standard:           $2,300/month
With lifecycle (IA after 30d, Glacier after 90d): $350/month
Savings: 85%

S3 Intelligent-Tiering

If you don’t know the access pattern, use Intelligent-Tiering. AWS automatically moves objects between tiers based on access frequency. Small monitoring fee ($0.0025/1000 objects) but zero retrieval fees.

EBS: Switch gp2 to gp3

gp3 is 20% cheaper than gp2 AND has better baseline performance (3000 IOPS vs 100 IOPS/GB for gp2).

# Modify in-place (no downtime)
aws ec2 modify-volume --volume-id vol-xxx --volume-type gp3

Savings: 20% on all EBS volumes with zero effort.

Delete Orphaned Resources

Resource How to Find Typical Waste
Unattached EBS volumes aws ec2 describe-volumes --filters Name=status,Values=available $50-500/month
Old snapshots aws ec2 describe-snapshots --owner-ids self (check age) $20-200/month
Unused Elastic IPs aws ec2 describe-addresses (not associated) $3.60/month each
Empty load balancers ALBs with 0 targets $16/month each
Incomplete multipart uploads S3 lifecycle rule to abort after 7 days Variable

General FinOps Practices (The Governance Layer)

Tagging Strategy (You Can’t Optimize What You Can’t Attribute)

tags = {
  team        = "starlight"
  service     = "availability-proxy"
  environment = "production"
  cost-center = "search-platform"
  owner       = "agnello.george"
}

Every resource tagged by team, service, and environment. Cost Explorer can then show: “Team Starlight spent £X this month, up 15% from last month.”

AWS Budgets + Anomaly Detection

resource "aws_budgets_budget" "monthly" {
  name         = "search-platform-monthly"
  budget_type  = "COST"
  limit_amount = "5000"
  limit_unit   = "USD"
  time_unit    = "MONTHLY"

  notification {
    comparison_operator = "GREATER_THAN"
    threshold           = 80
    notification_type   = "FORECASTED"
    subscriber_email_addresses = ["devops@company.com"]
  }
}
  • AWS Budgets: Alert at 80% of forecast (catch spikes before month-end)
  • Cost Anomaly Detection: ML-based — alerts on unexpected spend changes automatically

Weekly Cost Review Cadence

Frequency What Who
Daily Automated anomaly alerts On-call engineer (acknowledge/investigate)
Weekly Cost Explorer review — top 5 cost drivers DevOps team
Monthly Cost report by team/service — trends, optimizations Engineering leads
Quarterly Deep review — Savings Plans renewal, architecture changes Platform + Finance

Communicating Savings to Management

“Don’t say ‘let’s use Spot instances.’ Say: ‘Our CI/CD runners cost £X/month. Switching to Spot saves 70% — that’s £Y/month. Risk is low because builds are retryable. Implementation takes 2 days.’”

Present as a business case:

Current Spend Proposed Change Projected Savings Risk Effort
£3,000/month CI/CD Switch to Spot £2,100/month (70%) Low (retryable jobs) 2 days
£1,100/month non-prod Overnight scaling £770/month (70%) None (no users at night) 1 day
£2,300/month S3 logs Lifecycle policies £1,950/month (85%) None (old logs rarely accessed) 1 hour
£6,400/month Total £4,820/month 3 days work

Real-World Results

At our organisation, applying these practices over 6 months:

Optimization Monthly Savings
Karpenter (EKS node right-sizing) 30% compute reduction
Overnight scaling (kube-downscaler) 70% non-prod reduction
S3 lifecycle policies on log buckets 85% storage reduction
Spot instances for CI/CD runners 70% runner cost reduction
Right-sizing 5 production services 20-40% per service
VPC endpoints for S3/ECR Eliminated NAT processing charges

Key Takeaways

  1. Start with visibility — tag everything, use Cost Explorer, set budgets
  2. Go after the biggest items first — compute is usually 60%+ of the bill
  3. Automate scale-down — if nobody’s using it at night, turn it off
  4. Right-size based on data — not guesses. Use Compute Optimizer and Datadog metrics
  5. Choose the right pricing model — Savings Plans for stable, Spot for interruptible, On-Demand for unpredictable
  6. Eliminate waste — monthly audit for orphaned volumes, old snapshots, idle load balancers
  7. Make cost visible to teams — dashboards showing each team’s spend. People optimize what they can see
  8. Never sacrifice security or reliability — a £500/month saving that causes a £50,000 outage is not a saving

Tools Cheat Sheet

Tool What It Does Cost
AWS Cost Explorer Analyse spend by service, team, time Free
AWS Budgets Set spend thresholds, get alerts First 2 free
AWS Cost Anomaly Detection ML-based unexpected spend alerts Free
AWS Compute Optimizer Right-sizing recommendations Free
Karpenter EKS node optimization and consolidation Free (open source)
kube-downscaler Scale pods to zero outside business hours Free (open source)
Kubecost Per-pod, per-namespace cost visibility in K8s Free tier available
Spot Advisor Interruption rates by instance type/region Free (AWS tool)
Trusted Advisor Cost checks (requires Business support plan) Included with support

Conclusion

FinOps isn’t about being cheap — it’s about being smart. Every pound saved on idle infrastructure can be invested in better features, more resilience, or faster delivery. The best part: most of these optimizations are low-risk, low-effort, and high-impact. Start with the quick wins (lifecycle policies, overnight scaling, gp2→gp3), then work toward the strategic wins (Savings Plans, Karpenter, architecture changes).

The goal is a culture where cost is visible, waste is eliminated automatically, and every team owns their spend.


Want to discuss FinOps strategies for your organisation? Connect with me on LinkedIn.