Skip to main content

Savings Plans & Cost Optimisation

Owner: ali@jodapp.com · Baseline captured: 2026-07-04 · Progress re-read: 2026-07-19 (read-only ali-claude profile, account 140151801565, ap-southeast-1) · Basis: full on-demand list price.

This document is the source of truth for how JOD reduces its AWS bill. It is paired with the live Infrastructure Map. Read the map first if you have not — this page is the money side of the same picture.


Bottom line up front

We can cut the AWS bill from ~$2,925/mo to as low as ~$1,777/mo (‑39%) — but the order of steps matters more than any single discount. A boss-ready spreadsheet of every payment option lives in jod-aws-savings-proposal.xlsx.

Evidence: Strong

On-demand list total: EC2 compute $1,128 + RDS $1,059.84 + storage/network/other $722.54 ≈ $2,925/mo (~$35k/yr). This reconciles with the NDS May invoice (202605000003, $2,895.42 after their 2% discount) — i.e. this is what you already pay. All rates are exact: on-demand + RDS RI from the AWS Pricing / RDS-offerings APIs, EC2 Compute SP from the Savings Plans offering-rates API (the same data as the public compute-pricing page), 2026-07-04.

PlanWhat you doMonthly billYou saveUpfront cash
A — RightsizeData-driven Graviton right-sizing across the fleet. No commitment.$2,505$420 (14%)$0
B — 1yr No-UpfrontA + 1yr Compute SP + 1yr RDS RIs$2,146$779 (27%)$0
B2 — 1yr All-UpfrontA + 1yr commitments, prepaid$2,079$846 (29%)$12,452
C2 — 3yr PartialA + 3yr commitments, ~half prepaid$1,798$1,127 (39%)$13,606
C — 3yr All-UpfrontA + 3yr commitments, prepaid$1,777$1,148 (39%)$26,478

Recommended: Plan B (right-size + 1-year No-Upfront). It captures 68% of the maximum monthly saving with zero upfront cash and no 3-year lock. Paying $12,452 upfront (B2) buys only $67/mo more — a weak ~6% return on that cash. The lever that is big is the term: 3-year (C/C2) nearly doubles the discount for +$348–369/mo. Take Plan B now; move stable databases + compute to 3-year later, once self-serve and confident.

Where the savings come from — EC2 vs RDS

The totals above combine two independent tracks — EC2 (right-sizing + a Compute Savings Plan) and RDS (Reserved Instances). Neither depends on the other, so you can approve them separately:

Savings source1yr No-Upfront1yr All-Upfront3yr Partial3yr All-Upfront
EC2 — right-size (no commitment)$420$420$420$420
EC2 — Compute Savings Plan$154$181$306$311
EC2 subtotal$574$601$726$731
RDS — Reserved Instances$205$245$401$417
Combined (both)$779$846$1,127$1,148

Two things stand out. Right-sizing alone ($420/mo, free, no commitment) is the single biggest line — larger than any reservation. And because of it, EC2 is ~64–74% of the total while RDS Reserved Instances, though the largest commitment lever, are the smaller share. If you only did one track: EC2 alone saves $574–731/mo, RDS alone saves $205–417/mo.

The biggest free win is Plan A. You do not need a savings plan to get the first $365/mo — you just need to stop running two 8-vCPU servers at 1% CPU.


Progress — what has been captured

Banked so far: $442/mo ($5,300/yr), with zero commitment and zero upfront cash. For scale: Plan A — the entire free right-sizing track — was projected at $420/mo, and the work done so far has already passed it, through a mix of right-sizing ($408/mo) and waste cleanup ($34/mo), before the NDS exit and before buying a single reservation. The monthly bill has moved from ~$2,925 → ~$2,483 (‑15%).

Evidence: Strong

Like-for-like re-read using the same method as the baseline (AWS Pricing API, on-demand list, ap-southeast-1). The 2026-07-04 fleet of 25 running instances prices at $1,128.03/mo; the current fleet of 20 prices at $720.11/mo (as of 2026-07-19). The rebuilt baseline lands on the originally recorded $1,128 to the cent, so the delta is exact, not estimated. Terminations verified in the EC2 console: JodProDockerDemoV2 (i-0c8157fc58198ed7d), jodpro.qa.api (i-002eab88bab149f5c), jodpro.prod.api (i-010d60d4391b6efd6), jodpro.qa.frontend (i-09dee24623b2275f2), jodpro.prod.frontend (i-07dab87c96077fee2).

EC2 compute — $1,128.03 → $720.11 (‑$407.92/mo, ‑36%)

What changedBeforeAfterSaved $/mo
jodgig.prod.api-2 right-sizedc7g.2xlarge (16 GB)c7g.large (4 GB)182.43
jodpro.prod.frontend terminatedc6g.large57.23
jodpro.prod.api terminatedc6g.large57.23
jodpro.qa.frontend terminatedt4g.medium30.95
jodpro.qa.api terminatedt4g.medium30.95
jodgig.prod.reports right-sizedc7g.large (4 GB)t4g.medium (4 GB)29.86
JodProDockerDemoV2 terminatedt3.small19.27
EC2 total1,128.03720.11407.92

Two results worth reporting upward:

  • api-2 beat the plan — but is still $29.86/mo overpriced. The plan called for t4g.xlarge ($123.81) and deliberately kept 16 GB of RAM, because no memory metrics existed and we refused to guess. Moving it to c7g.large (4 GB) banked $182.43/mo — $63/mo more than the plan projected. It is not the right landing spot, though: c7g.large and t4g.medium are both 2 vCPU / 4 GB, and c7g.large costs twice as much ($60.81 vs $30.95). The only thing that premium buys is 2.0 vCPU sustained instead of a 0.4 vCPU burstable baseline — and api-2 draws 0.0058 vCPU. See the API pair analysis below.
  • Retiring jodpro beat right-sizing it. The plan proposed shrinking the four jodpro boxes to t4g targets for $83.52/mo. Terminating them outright banked $176.36/mo — more than double — plus $19.27 for the demo box. The cheapest server is the one that does not run, and no right-sizing exercise can beat deleting a workload that nobody needs.

Waste and databases — ‑$33.65/mo

What changedSaved $/mo
jodpro RDS database terminated (db.t4g.micro · mysql)18.25
4 idle Elastic IPs released (18.136.1.40, 54.251.205.44, 54.254.14.30, 54.251.52.130)14.60
JODv2-REPORT-PROD-CRON-env terminated, disk released0.80
Subtotal33.65

Where the bill stands

Monthlyvs baseline
Baseline 2026-07-04 (on-demand list)$2,925
Today (2026-07-19)~$2,483‑$442 (‑15%)
After the remaining free work below (no commitment)~$2,149‑$776 (‑27%)
After Plan B on top (1yr No-Upfront SP + RDS RIs)~$1,864‑$1,061 (‑36%)
Evidence: Directional

The bottom two rows are forward projections re-based on the current fleet, not the 2026-07-04 one: fully right-sized EC2 lands at $386.20/mo (from $720.11 today), of which the always-on production baseline is $301.06/mo (a 1yr No-Upfront Compute SP at 27.7% ≈ $83/mo), and the five surviving prod databases on 1yr No-Upfront RIs save $201/mo. The Plan B figure differs from the tables above because the fleet those tables describe no longer exists — you already deleted part of it, and the right-sizing targets are now driven by measured memory rather than the conservative RAM-preserving guesses.

Still available, still free — ~$335/mo

No commitment, no upfront cash, no architecture change:

ActionSaves $/moStatus
jodgig.prod.api-3 c7g.2xlarge → t4g.medium212.29Open — highest-value action left
jodgig.prod.api-2 c7g.large → t4g.medium29.86Open — finish the job started on 07-16
jodgig.prod.frontend c7g.large → t4g.medium29.86Open — RAM unchanged (4 GB → 4 GB)
jodgig.qa.api t4g.medium → t4g.small15.48Open
jodgig.qa.frontend t4g.medium → t4g.small15.48Open
jodgig.prod.frontend-board + jodgig.qa.frontend-board terminated30.96Planned
Delete unattached volume vol-06c22cfc8ea0349cb (8 GB gp3, idle since 2024-08-05)0.77Open

jodgig.prod.reports (c7g.large → t4g.medium, $29.86/mo) was on this list and is now done — see the EC2 compute table above.

The API pair — the largest remaining win ($242.15/mo)

api-2 + api-3 cost $304.05/mo today. Both belong on t4g.medium$61.90 for the pair, saving $242.15/mo, which is two-thirds of everything left on the table.

Method — why percentages lie. CloudWatch CPUUtilization is a percentage of the whole instance, so the same workload reports a different number on every instance size. The doc's original "api-2 p95 0.19%" meant 0.19% of 8 vCPUs = 0.0152 vCPU absolute; on a 2-vCPU box that identical work reads as 0.76%. Always convert to absolute vCPU (% × vCPU) before comparing across sizes. A t4g.medium earns 24 credits/hr on 2 vCPUs, which is a 0.4 vCPU sustained baseline — that is the number to compare against.

Evidence: Strong

CloudWatch 30 days to 2026-07-16, converted to absolute vCPU. api-2: 0.0058 vCPU mean (1.5% of a t4g.medium baseline). api-3: 0.2185 vCPU mean, 0.343 p95, 1.03 peak 1-hr. Memory measured directly via htop on api-3 under production load: ~1 GB — so t4g.medium's 4 GB is 4× the working set. Baselines and credit rates from the AWS burstable credit table (t4g.medium: 2 vCPU, 20% baseline, 24 credits/hr, 576 cap, Unlimited mode by default).

api-2 is a warm standby — it has served no production traffic for at least 30 days (0.09 GB in over 7 days, vs api-3's 287 GB; a 4,700× packet gap). That does not make it disposable: it must be able to absorb api-3's entire load on failover, which is why it goes to t4g.medium and not t4g.small.

Failover safety check — api-2 on t4g.medium carrying 100% of api-3's load (demand inflated 25% to account for Graviton3 → Graviton2):

Load levelOn t4g.mediumCredits/hrResult
Sustained (mean)13.7% CW16.4 spent vs 24 earnedStill accruing
p9521.4% CW25.7 vs 24Net ‑1.7/hr — 340 h to drain a full cap
Peak 1-hr64.2% CW77.1 vs 24Net ‑53/hr — 10.8 h of cap; peaks last ~1 h

The 24-hour average (13.7%) stays below the 20% baseline, so in Unlimited mode there is no surplus charge and no throttling. Empirical backup: every t4g box in the fleet today sits pinned at the 576-credit cap with zero surplus — including jodgig.prod.cron, the busiest one.

Why not the alternatives: t4g.large (8 GB, $61.90) costs more than the c7g.large it would replace and buys RAM that a 1 GB working set does not need. t4g.small (2 GB, $15.48) has identical CPU to t4g.medium — same 2 vCPU, same 20% baseline, same 24 credits/hr — so it is purely a RAM decision, and 2 GB against a 1 GB working set is too thin for a production API that is also the failover target.


The one prerequisite: leave NDS first

You are not billing directly with AWS — and NDS keeps your Savings Plan discount

Account 140151801565 is still a member of NDS's AWS Organization (management account 767010522689, org o-0iovcybjee). NDS told us the migration would finish end of May. As of 2026-07-04 it has not. This is a reseller arbitrage, not a bill shock risk: you already pay on-demand, so leaving is strictly cheaper.

Evidence: Strong

NDS invoice 202605000003 (May 2026): total $2,895.42. EC2 "Compute Instance" is billed entirely at On-Demand rates ($1,135.18 — e.g. $0.3332/hr for c7g.2xlarge), matching the AWS Pricing API to the cent. Yet Cost Explorer shows that same compute as SavingsPlanCoveredUsage $1,097.71, canceled by SavingsPlanNegation ‑$1,097.71 — a Savings Plan owned by NDS's payer account. AWS discounts the compute for NDS; NDS invoices you full list.

Why this matters (and why there is no bill shock):

  • Your 25 EC2 servers show $0/hr in the AWS console because NDS's Savings Plan covers them there — but the NDS invoice charges you the full on-demand rate anyway. The discount is theirs.
  • So leaving NDS does not raise your compute bill — you are already paying on-demand. At worst you lose NDS's token 2% discount (~$58/mo). That is the entire downside.
  • The upside: self-serve lets you buy your own Savings Plan and recapture the spread NDS keeps (~$180–240/mo), plus RDS Reserved Instances (which NDS is not buying for you either).
Monthly
NDS invoice today$2,895.42on-demand − 2% NDS discount
Self-serve, do nothing~$2,953.70+$58/mo (lose the 2% only)
Self-serve + your own SP~$2,712recapture the SP spread
Self-serve + SP + RDS RIs + rightsize~$1,800–2,100the full plan

Action: ask NDS, in writing, to run RemoveAccountFromOrganization for account 140151801565, or complete standalone sign-up so you can leave yourself. Full checklist in the billing migration section below.


The correct order of work

STEP 0  Exit NDS  →  become your own payer            (billing prerequisite)   ⬜ BLOCKED ON NDS
STEP 1 Rightsize the 2 idle c7g.2xlarge servers ($365/mo, no commitment) 🟡 api-2 DONE, api-3 OPEN
STEP 2 Kill waste: idle EIPs, unattached disks, gp2 (~$50/mo, no commitment) 🟡 MOSTLY DONE (~$34/mo)
STEP 3 Buy RDS Reserved Instances on stable prod DBs (~$201/mo, buyable now) ⬜ OPEN — 5 DBs, not 6
STEP 4 Buy your own EC2 Compute Savings Plan (after Step 0 + Step 1) ⬜ OPEN
STEP 5 (Optional) Schedule QA off-hours (~$150/mo) ⬜ OPEN

Buying a 1–3 year commitment before rightsizing (Step 1) locks in the waste for the whole term. Always rightsize first, then reserve the smaller box.

Where you are: Steps 1–2 are $412/mo banked with no commitment (see Progress). The single highest-value action left is finishing Step 1 on jodgig.prod.api-3t4g.medium (~$212/mo), with api-2 following it to the same target ($30/mo). Step 3 is buyable today and does not wait on NDS, because reservations travel with the account.


Step 0 — Exit NDS (billing prerequisite)

There is no compute cost cliff — you already pay on-demand via NDS, so your bill does not jump when you leave (you only lose NDS's 2% discount, ~$58/mo). The checklist is just about a clean handover:

☐ Confirm YOU control the root email of account 140151801565 (not NDS)
☐ Add your own payment method to the account (Billing → Payment methods)
☐ Finish Step 1 (rightsize) so the SP you buy in Step 4 is sized to a lean fleet
☐ Soon after standalone: buy your own Compute Savings Plan (recaptures ~$180–240/mo NDS keeps)
☐ Buy RDS RIs on your own payment method

How you leave depends on how NDS created the account:

How NDS set it upCan you click "Leave organization"?What to do
Invited your existing accountYes, once standalone billing info is addedAdd payment method + verify, then Organizations → Leave organization
Created the account for youNo (greyed out) until standalone sign-up is doneHave NDS run RemoveAccountFromOrganization, or finish AWS sign-up first

Fastest clean path: make NDS remove you, in writing, since they already missed the deadline once.


Step 1 — Rightsize on real CPU history (the biggest free win)

This is $420/mo with no commitment and no architecture change. The sizing is driven by each instance's 30-day p95 CPU — not a rule of thumb. p95 is the right metric: the scary 84–99% max spikes are momentary, while the sustained load is near-zero almost everywhere.

Evidence: Strong

CloudWatch CPUUtilization, 30 days (2026-06-04 → 07-04): p95 is below 2% on all but two of 25 instances. e.g. jodgig.prod.frontend (c7g.large) p95 0.27%; jodgig.prod.api-2 (c7g.2xlarge) p95 0.19%. The exceptions: jodgig.prod.cron (p95 19%, real burst load — keep) and JodProDockerDemoV2 (p95 95% — not idle, investigate).

Two rules make this safe and change-free:

  • Graviton-only (t4g). Every target is ARM64, same chip family as your current c6g/c7g/t4g. No Dockerfile, base-image, or build change — just a smaller/cheaper instance of the same architecture.
  • RAM preserved. No memory metrics exist (the CloudWatch agent is not installed), so every target keeps at least the current RAM. We move from compute-optimised (c, 2 GB/vCPU) to burstable (t4g) because these workloads are idle-with-bursts — exactly what burstable is for.
InstanceNow (RAM)p95 CPU→ Target (RAM)Now $/moAfter $/moSave
jodgig.prod.api-2c7g.2xlarge (16 GB)0.19%t4g.xlarge (16 GB)243.24123.81119.43
jodgig.prod.api-3c7g.2xlarge (16 GB)5.70%t4g.xlarge (16 GB)243.24123.81119.43
jodgig.prod.frontendc7g.large (4 GB)0.27%t4g.medium (4 GB)60.8130.9529.86
jodgig.prod.reportsc7g.large (4 GB)0.62%t4g.medium (4 GB)60.8130.9529.86
jodpro.prod.frontendc6g.large (4 GB)0.66%t4g.medium (4 GB)57.2330.9526.28
jodpro.prod.apic6g.large (4 GB)0.63%t4g.medium (4 GB)57.2330.9526.28
jod.prod.metabaset3a.large (8 GB, x86)3.11%t4g.large (8 GB)68.9161.907.01
jodpro.qa.apit4g.medium (4 GB)0.56%t4g.small (2 GB)30.9515.4815.48
jodgig.qa.apit4g.medium (4 GB)0.79%t4g.small (2 GB)30.9515.4815.48
jodpro.qa.frontendt4g.medium (4 GB)0.27%t4g.small (2 GB)30.9515.4815.48
jodgig.qa.frontendt4g.medium (4 GB)0.23%t4g.small (2 GB)30.9515.4815.48
Total$420.04

Notes that answer "is t4g.medium really right for QA?" — no, it was too big: your QA app servers run at p95 < 1%, so t4g.small (2 GB) is plenty. The tiny/already-right boxes (t4g.small/micro prod, jodgig.prod.cron) stay as-is.

  • metabase must stay on x86 — treat its $7.01 row as $0. The platform requires x86, so the t4g.large (ARM) target does not apply and the table row above is superseded. Under that constraint t3a.large is already the cheapest 8 GB x86 instance in ap-southeast-1 — every alternative costs more (t3.large $77.09, m6a.large / m5a.large $78.84, t2.large $85.26, m5.large $87.60, all against $68.91). This box is already right-sized; there is nothing to do. The only lever left is t3a.medium (x86, 4 GB, $34.46 → saves $34.45/mo), which halves the RAM — check the Metabase JVM heap first, since Metabase is memory-hungry and this violates the RAM-preserved rule above. Not recommended without a measurement.
  • Phase 2 — resolved 2026-07-16, and it went further than this note expected. The plan was to install the CloudWatch agent, measure memory for two weeks, then drop the c7g.2xlarge pair from t4g.xlarget4g.large if they used < 8 GB. A direct htop reading on api-3 under production load settled it without the agent: ~1 GB working set. That is not merely < 8 GB — it is < 2 GB, so the pair lands on t4g.medium (4 GB), two sizes below what this note anticipated. The 16 GB preserved in the table above was pure caution, and it costs ~$180/mo to keep. Memory is still worth instrumenting properly, but it is no longer blocking this decision.
  • JodProDockerDemoV2 is terminated (2026-07-16). This note previously warned against killing it because it ran at p95 95% CPU and looked like it was doing real work. It was retired deliberately along with the rest of the jodpro fleet.

Step 2 — Kill waste (no commitment) — mostly done

Original estimate $50/mo; **$34/mo captured**, ~$32/mo still open (mostly the frontend-board pair).

ItemEst. $/moStatus
Release 4 idle Elastic IPs14.60Done — all four released
Terminate stopped cron box JODv2-REPORT-PROD-CRON-env0.80Done — disk released too
Kill demo box JodProDockerDemoV2 (t3.small)19.27Done — terminated
Convert gp2 → gp3 (EC2 volumes)~0.20Done — no gp2 EBS volumes remain
Terminate frontend-board pair (prod + qa, t4g.small each)30.96⬜ Planned
Delete unattached volume vol-06c22cfc8ea0349cb0.77⬜ Open
Convert gp2 → gp3 (RDS)0.00Void — no saving exists (see below)

frontend-board — the remaining kill

jodgig.prod.frontend-board (i-0e11ca49e09dd716c) and jodgig.qa.frontend-board (i-0282c085dc7b73f6f) are both t4g.small at $15.48/mo each = $30.96/mo. They were inside the 2026-07-04 count of 25 but were never listed separately, because at t4g.small they were already right-sized — the plan had nothing to shrink. Terminating them is worth more than shrinking them ever was.

Evidence: Strong

ec2 describe-instances 2026-07-16: both running, both t4g.small, both in the jodgig VPCs. Priced at the exact t4g.small on-demand rate for ap-southeast-1 ($0.0212/hr × 730 = $15.48/mo).

Correction — RDS gp2 → gp3 saves nothing here

Evidence: Strong

AWS Pricing API, ap-southeast-1, 2026-07-16: RDS GP2-Storage = $0.138/GB-mo and GP3-Storage = $0.138/GB-mo — identical. EBS is the one that differs: gp2 $0.12 → gp3 $0.096/GB-mo (‑20%).

The original ~$12/mo gp2→gp3 estimate applied the EBS discount to RDS storage. It does not transfer: in this region RDS charges the same rate for both. The two remaining gp2 databases (jodgig-qa-sync 433 GB, rds-jod-test-reports 20 GB) would save $0/mo from a conversion. gp3 may still be worth it for the configurable IOPS baseline, but not as a cost action — do not book it as savings. The EC2 side of that estimate was real and is already done.

Elastic IPs — all four now in use, none idle (done 2026-07-19)

The four idle EIPs are released, and the four that remain are all in use and correctly tagged. None should ever be released:

EIPAttached toRole
13.251.207.51jod.prod.haproxy (i-08d60a03c51ed35c2)prod ingress — reserved IP behind Cloudflare
3.1.7.254jod.qa.haproxy (i-0faaf01da0395180f)qa ingress — new, replaces the auto-assigned IP
52.221.32.130NAT gateway nat-03e1ba4b7af7c76f7 (prod-vpc-NAT-outbound)Load-bearing — outbound internet for every private prod instance
3.1.123.87NAT gateway nat-02f932aac7b5b27ec (qa-vpc-NAT-outbound)Load-bearing — same, for QA

Two fixes landed here:

  • jod.qa.haproxy now has a reserved Elastic IP (3.1.7.254). It previously ran on an auto-assigned address (54.169.122.201, IpOwner: amazon) that changes on every stop/start and would break the Cloudflare record. Now IpOwner is the JOD account (140151801565), so the IP survives resizes — QA is finally at parity with prod. This was cost-neutral: since 1 Feb 2024 AWS bills every in-use public IPv4 at ~$3.65/mo whether elastic or auto-assigned, so the unstable IP was already being paid for. A resilience fix worth $0, not a savings item.
  • The two NAT gateway EIPs were retagged from the ambiguous prod-vpc / qa-vpc to prod-vpc-NAT-outbound / qa-vpc-NAT-outbound, so nobody mistakes a load-bearing gateway address for idle waste. (AWS refuses to release an EIP bound to a NAT gateway anyway, so this was a clarity fix, not an outage risk.)

Step 3 — RDS Reserved Instances (the main event)

RDS is 72% of your bill and is covered by nothing. Savings Plans do not apply to RDS — the mechanism here is Reserved Instances (RIs). Reserve only the stable production databases; QA/test databases should be scheduled off (Step 5), not reserved.

Evidence: Strong

RDS reserved-offerings API, single-AZ (all our DBs are MultiAZ=false), 2026-07-04. On-demand at 730h. Reserve the six stable production databases below; per-DB × per-option detail is in jod-aws-savings-proposal.xlsx (tab "RDS Reserved").

Five prod DBs — the buy list as of 2026-07-16 (full per-DB matrix in the workbook):

DatabaseClassOn-demand $/mo1yr No-Up $/mo3yr All-Up $/mo
jodgig (whale)db.m7g.2xlarge · mysql684.01526.33362.44
jodgig-replica-1db.t4g.medium · mysql74.4658.4042.28
metabasedb.t4g.medium · postgres74.4658.4042.28
jodappdb.t4g.small · postgres37.2329.2021.14
jodgig-reportsdb.t4g.micro · mysql18.2514.6010.56
Total (prod)$888.41$686.93$478.70
jodpro was in this list and is now gone

The 2026-07-04 version of this table had a sixth row — jodpro (db.t4g.micro · mysql, $18.25/mo). That database has since been terminated (credited in the progress section). Do not buy a reservation for it. The totals above are the live five-database buy list.

Every payment option — this is the table for the approval decision:

Payment optionRDS $/moSave $/moUpfront cash
On-demand (today)906.66
1yr No Upfront701.53205$0
1yr Partial Upfront680.02227$4,078
1yr All Upfront661.59245$7,939
3yr Partial Upfront505.90401$9,093
3yr All Upfront489.26417$17,613
This table still includes jodpro — the decision does not change

These rows were priced across all six databases on 2026-07-04. With jodpro terminated, each $/mo figure drops by roughly $15–18, but the savings deltas barely move (1yr No Upfront: $205 → $201), because jodpro was 2% of the RDS bill. The approval decision is unaffected, so the rows are left as priced rather than re-derived. Use the five-database totals above for the actual purchase.

AWS offers no 3-year No-Upfront for RDS — 3-year requires Partial or All upfront. All 1-year No-Upfront RIs break even immediately (month 0, zero cash).

Recommended approach — two phases, low risk:

  1. Now (even a small step before self-serve is fine — RIs travel with the account): put all five surviving prod DBs on 1-year No-Upfront. Zero cash, breaks even immediately (month 0), saves ~$201/mo.
  2. After 2–3 stable months as self-serve: convert the small, definitely-permanent DBs (jodapp, jodgig-reports, metabase) to 3-year. Keep the whale jodgig on 1-year until you have tested whether it can drop to m7g.xlarge — it averages 20% CPU but spikes to 99%, so do not lock a 3-year reservation onto it yet.
Evidence: Directional

RDS jodgig CPU: avg 20.3%, max 98.9% (30 days). Low average suggests headroom, but the 99% peaks are real load — m7g.xlarge (half the size) may not survive peaks. Test before reserving 3 years.

How to buy one (whale example — get the offering ID, then purchase):

# 1. find the 1yr No-Upfront single-AZ offering id
aws rds describe-reserved-db-instances-offerings \
--db-instance-class db.m7g.2xlarge --product-description mysql \
--duration 31536000 \
--query "ReservedDBInstancesOfferings[?MultiAZ==\`false\` && OfferingType=='No Upfront'].ReservedDBInstancesOfferingId" \
--output text

# 2. purchase it
aws rds purchase-reserved-db-instances-offering \
--reserved-db-instances-offering-id <offering-id-from-step-1> \
--db-instance-count 1

Step 4 — EC2 Compute Savings Plan (after self-serve)

Once you are your own payer and have rightsized (Step 1), replace NDS's coverage with your own Compute Savings Plan. Use Compute SP (not EC2-Instance SP) — it is flexible across instance family, size, and region, which suits a fleet that still changes.

Evidence: Strong

EC2 Compute SP rates are exact — from the Savings Plans offering-rates API (the same data as the public compute-pricing page), t4g Linux ap-southeast-1. The discount is uniform across t4g sizes: 27.7% (1yr no-up) → 55.8% (3yr all-up). Applied to the right-sized production compute baseline of $557/mo (QA is handled by scheduling, not an SP).

Payment optionDiscountEC2 compute $/moSave $/moUpfront
On-demand (right-sized)557
1yr No Upfront27.7%403154$0
1yr Partial Upfront31.1%384173$2,303
1yr All Upfront32.5%376181$4,513
3yr No Upfront51.3%271286$0
3yr Partial Upfront55.0%251306$4,513
3yr All Upfront55.8%246311$8,865

Note the standout: 3-year No-Upfront gives 51% off for zero cash — unlike RDS, Compute SPs do offer 3-year No-Upfront. If you're confident the compute baseline is stable, it's the best cash-free deep cut.

Size the hourly commitment to your steady baseline only (roughly the always-on prod servers), not the peak. Anything above the commitment simply runs at on-demand — under-committing is cheap to fix, over- committing is locked for the term. Start conservative.


Step 5 — Schedule QA off-hours (optional, ~$150/mo)

QA does not need to run nights and weekends. QA EC2 ($193/mo) + QA RDS ($147/mo) ≈ $340/mo of resources that are idle ~70% of the week.

Evidence: Assumption

Estimate only: running QA ~50h/week instead of 168h ≈ 70% off the QA compute + DB line, ~$150/mo. Needs automation (AWS Instance Scheduler, or an EventBridge + Lambda stop/start). RDS auto-restarts after 7 stopped days, so scheduling must restart weekly.

Do not buy RIs for QA databases — a reservation you turn off nightly is wasted money. Schedule instead.


Decision summary

If you want…Do thisSaves
Already banked (2026-07-04 → 07-16)Right-sized api-2, retired jodpro + demo box, released idle EIPs~$412/mo
The safest next move, zero cash, this weekFinish Step 1 — the API pair to t4g.medium ($242), frontend, reports, QA pair, kill frontend-board~$365/mo more
Best commitment-free move that does not wait on NDSStep 3: 1yr No-Upfront RIs on the 5 prod DBs~$201/mo more
Maximum savings with no upfront cashPlan B: rightsize + 1yr No-Upfront (SP + RIs)$779/mo
Deep cut, still no cash (if compute is stable)rightsize + 3yr No-Up SP + 1yr No-Up RDS~$865/mo ($0 upfront)
Deepest savings, willing to pay upfrontrightsize + 3yr All-Upfront (SP + RIs)$1,148/mo ($26.5k upfront)

The last three rows are the original 2026-07-04 projections, kept as-issued so the plan can be judged against what it promised. They are measured from the $2,925 baseline, so the ~$412/mo already banked is part of those figures, not additional to them.

Recommended: do Steps 1–2 immediately (free, reversible). Finish the NDS exit (Step 0). Then take Plan B (1-year, no upfront) — zero cash, no lock-in, and it captures 68% of the maximum monthly saving. Paying $12.5k upfront for the 1-year all-upfront buys only ~$67/mo more (~6% return); not worth it. The bigger lever is the term — 3-year nearly doubles the discount — so move stable databases + compute to 3-year once standalone and confident. The full option-by-option comparison is in jod-aws-savings-proposal.xlsx.


Appendix — how these numbers were produced

Evidence: Strong

All figures come from live AWS reads on 2026-07-04 via a read-only IAM user (ali-claude): ec2 / rds describe APIs (inventory), Cost Explorer get-cost-and-usage + get-reservation-purchase- recommendation (spend), the Pricing API (EC2 on-demand), the RDS reserved-offerings API (RI rates), the Savings Plans offering-rates API (SP rates), and CloudWatch CPUUtilization (rightsizing). The per-resource workbook is in the paired cost spreadsheet.

  • Why on-demand list, not the $1,958 console figure: the console hides EC2 compute behind NDS's Savings Plan. After self-serve that discount is gone, so planning on-demand is the honest baseline.
  • EC2 Savings Plan rates are estimates (~22% / ~33%), calibrated from two live API data points and clearly marked. Everything else (on-demand, RDS RI) is exact from AWS APIs.
  • Tax (~$162/mo) is excluded from the optimisation math; it scales with the bill, so cutting spend cuts tax proportionally.