Cost Management¶
Every new EC2 instance requires a cost projection before deployment. Use the pricing table below and factor in EBS, Savings Plan discounts, and NAT Gateway data transfer.
Mandatory Cost Projection Rule¶
Cost projection required for all new EC2 instances
When adding a new EC2 instance via Terraform, you must include a cost projection in the PR/MR description covering: 1. EC2 instance On-Demand monthly rate 2. EBS storage cost (all volumes) 3. Savings Plan projected cost (~47% discount for 3yr No Upfront) 4. Total monthly estimate
EC2 Instance Pricing (us-west-2 On-Demand)¶
| Instance Type | vCPU | RAM | $/month (On-Demand) | $/month (Savings Plan ~47% off) |
|---|---|---|---|---|
| t3.micro | 2 | 1 GB | $7.59 | ~$4.02 |
| t3.small | 2 | 2 GB | $15.18 | ~$8.05 |
| t3.medium | 2 | 4 GB | $30.37 | ~$16.10 |
| t3.large | 2 | 8 GB | $60.74 | ~$32.19 |
| t3.xlarge | 4 | 16 GB | $121.47 | ~$64.38 |
| t3.2xlarge | 8 | 32 GB | $242.94 | ~$128.76 |
Savings Plan
CWIQ.IO uses a Compute Savings Plan (~47% discount, 3-year No Upfront). New instances automatically benefit from this plan as long as it has available commitment. See terraform-plan/docs/cost/COST_OPTIMIZATION.md for the full analysis.
EBS Storage Pricing (us-west-2)¶
| Volume Type | Price |
|---|---|
| gp3 | $0.08/GB-month |
| gp2 | $0.10/GB-month |
| io1/io2 | $0.125/GB-month + IOPS |
All new volumes use gp3 by default. EBS volumes are independent of the Savings Plan — storage costs are not discounted.
Common volume cost examples:
| Volume Size | Monthly Cost (gp3) |
|---|---|
| 20 GB | $1.60 |
| 50 GB | $4.00 |
| 100 GB | $8.00 |
| 250 GB | $20.00 |
Deployed Server Cost Reference¶
| Server | Instance | Root | /data | /var/lib/containerd | Est. Monthly (On-Demand) |
|---|---|---|---|---|---|
| GitLab (shared) | t3.xlarge | 50 GB | 250 GB | 100 GB | ~$170-180 |
| Nexus | t3.large | 50 GB | 250 GB | 100 GB | ~$100 |
| Authentik (×2) | t3.medium | 20 GB | — | — | ~$30 each |
| Vault | t3.small | 20 GB | — | — | ~$20 |
| Ansible | t3.small | 20 GB | 50 GB | — | ~$20 |
| SonarQube | t3.large | 100 GB | 250 GB | 100 GB | ~$100 |
| DefectDojo | t3.medium | 50 GB | 100 GB | 50 GB | ~$50 |
| Orchestrator DEV | t3.large | 30 GB | 200 GB | 150 GB | ~$90 |
| LangFuse | t3.large | 30 GB | 100 GB | 50 GB | ~$75 |
| Demo | t3.medium | 30 GB | 100 GB | 50 GB | ~$50 |
| Icinga (shared) | t3.small | 20 GB | 50 GB | — | ~$20 |
| Prometheus | t3.medium | 20 GB | 200 GB | — | ~$50 |
| Loki | t3.medium | 20 GB | 200 GB | — | ~$50 |
| Grafana | t3.small | 20 GB | 20 GB | — | ~$20 |
Infrastructure Overhead¶
| Component | Monthly Cost |
|---|---|
| NAT Gateway — Shared-Services (2×, HA) | ~$84 (base + transfer) |
| NAT Gateway — Dev (1×, single) | ~$42 (base + transfer) |
| EKS Control Plane | $73 (fixed) |
| ALB — GitLab | ~$20-25 |
| EIP (per NAT Gateway) | ~$3.50 each |
| Route53 hosted zones | ~$0.50/zone/month |
Default AMI for New Instances¶
Use AlmaLinux 9 for all new instances
All new EC2 instances must use AlmaLinux 9.7 unless there is a documented reason for a different OS. AlmaLinux 10 has known incompatibilities with SSSD proxy mode.
| AMI ID | OS | Region |
|---|---|---|
ami-02169c46e1cfcd5e7 |
AlmaLinux 9.7.20251118 x86_64 | us-west-2 |
ami-08952be33a4ff3495 |
AlmaLinux 10.1.20251124 x86_64 | us-west-2 — only if AL10 explicitly required |
Copy the AMI ID from an existing module:
grep ami_id terraform-plan/organization/environments/shared-services/ec2-instances/ansible/variables.tf
Cost Projection Template¶
When adding a new EC2 instance, include this in your MR description:
## Cost Projection: <service-name>
| Item | Size/Type | Monthly Cost |
|------|-----------|--------------|
| EC2: t3.medium (On-Demand) | — | $30.37 |
| EBS root (gp3) | 30 GB | $2.40 |
| EBS /data (gp3) | 100 GB | $8.00 |
| EBS /var/lib/containerd (gp3) | 50 GB | $4.00 |
| **Total (On-Demand)** | | **$44.77** |
| **Total (Savings Plan ~47% off compute)** | | **~$32** |
Related Pages¶
- Multi-Account Setup — Profile configuration for cost attribution
- NAT Gateway — NAT cost breakdown and HA vs single NAT trade-off
- Server Inventory — All deployed servers