Skip to content

Pricing sources ​

Where every number comes from, how long it is cached, and what happens when a lookup fails.

Sources by dimension ​

DimensionSourceLive?
EC2 on-demandAWS Price List API (pricing:GetProducts)Yes
EC2 spotEC2 Spot Price History (ec2:DescribeSpotPriceHistory)Yes
EBS per-GB-monthAWS Price List APIYes
EBS IOPS / throughputstatic constantsNo
Data transferstatic table, us-east-1 rates for all regionsNo
Load balancerstatic tableNo

The Price List API client is pinned to us-east-1 because that is the global endpoint for the service, regardless of which region you are pricing.

The two IAM permissions above are the only ones the server needs. Both return public list prices — no customer-specific or billing data.

Cache TTLs ​

EntryTTLWhy
On-demand24 hourslist prices change rarely
Spot15 minutesspot moves constantly
EBS24 hoursas on-demand
Transfernever expiresstatic table, seeded at boot
Load balancernever expiresstatic table, seeded at boot

The cache is in-memory and miss-driven — there is no catalogue warm-up. The first query for an instance type fetches it; subsequent queries within the TTL do not. A stale entry counts as a miss.

Spot cache keys include the availability zone, since spot prices differ per AZ.

Retry behaviour ​

Transient AWS errors are retried a small number of times with backoff.

Permanent errors are not retried — there is an allowlist of transient error codes, and anything outside it fails immediately. Retrying an InvalidParameterValue three times just delays the error.

Failure modes ​

No AWS credentials at boot. The server still starts. It serves whatever prices are already cached and reports the rest as unavailable, and every cost response carries pricingAvailable: false so the console can label it. This is what keeps local development and CI working without credentials.

Cache miss with no fetcher. Not found. The node group lands in coverage.unpriced.

Unsupported region. 16 regions are mapped from region code to Price List "location" string. A region outside that map returns an unsupported-region error rather than a fallback price.

Spot history empty. Not found. No fallback to on-demand — silently substituting the on-demand price would overstate cost on a spot fleet, which is worse than admitting the gap.

Invalid product data. Products with price <= 0, vcpu <= 0 or memGiB <= 0 are rejected rather than cached.

Spot and instance shape ​

Spot price history returns a price but not the instance's vCPU/memory shape. The shape is resolved from cached on-demand data, fetching it if necessary, so unit costs are correct. If the shape cannot be resolved the price is still returned but unit costs are zero — the whole-node price is right, the per-vCPU split is not available.

Discounts ​

Console figures are at list price; there is no org-level EDP setting yet. The pricing API accepts an EDP percentage per request, validated as 0 < d ≤ 100. Invalid values are ignored, not clamped, so a malformed discount never silently alters a price. Prices are cached undiscounted and a discount is applied on read, so it is never applied twice.

Reserved Instances and Savings Plans are not modelled.

EBS pricing detail ​

Only the per-GB-month storage price is fetched live. IOPS and throughput rates are static because the Price List API models them as separate product families with naming that varies by volume type and region, and getting that wrong would misprice provisioned-IOPS volumes.

TypeBaseline IOPSBaseline throughput$/IOPS-mo$/MBps-mo
gp33000125 MB/s0.0050.04
gp2bundledbundled——
io1——0.065—
io2——0.065—
st1500500——
sc1250250——
storage = sizeGiB × pricePerGBMonth
gp3:     iops = max(0, iops − 3000) × 0.005
         tput = max(0, mbps − 125)  × 0.04
io1/io2: iops = iops × 0.065
total   = storage + iops + tput, then EDP discount

Transfer table ​

See AWS network costs for the rates. Responses report the source as a static table so the console can label them approximate.

There is no VPC peering rate in the table.

Freshness ​

Every price response carries an asOf timestamp from when it was fetched. For spot in particular, treat the figure as a point-in-time sample rather than a current quote.

Every figure in KubeSpend traces to a real cloud price. Where we cannot measure something, we say so.