Cache Savings Calculator — JavaScript source
See what prompt caching saves — uncached vs cached cost over N requests, with the write-premium break-even point.
This is the JavaScript implementation — the same logic the interactive tool runs, in a shareable, citable form.
/**
* Cache Savings Calculator — uncached vs prompt-cached LLM cost comparison.
*
* Language: JavaScript (ES2022+, ES module; runs unmodified in Node 18+
* and modern browsers)
* Source: CosmoDev polyglot showcase port of the Cache Savings Calculator
* tool, ported from src/lib/cacheSavings.ts (the canonical
* TypeScript implementation).
* Tool: https://dev.cosmolabs.org/tools/cache-savings-calculator
* License: display source — part of CosmoDev's polyglot tool pages.
*
* Design goals:
* - Pure + deterministic; never throws.
* - Functionally equivalent to the TS reference: same inputs -> same outputs.
* - Self-contained: stdlib only (no npm dependencies).
*
* The TS original takes a full AiModel record but reads only its four pricing
* rates, so this port narrows the parameter to exactly those fields. Any
* missing (null) rate makes every output null — the caller renders an
* explanatory empty state instead of partial math. All rates are per-1M-token
* USD, mirroring the cost conventions of llmCost.ts.
*
* Reference vectors (fixture model 10 / 50 / 1 / 12.5 — see
* cacheSavings.test.ts, the lock-step contract every port mirrors):
* 10k in / 1k out / 5 hits -> uncached 0.75, cached 0.425, savings 0.325,
* 43.333...% saved, break-even 13 hits. At 1 hit caching LOSES 0.035 (an
* honest negative saving). hits < 1 counts as 1. Zero tokens -> zero costs
* with 0%. cacheRead 0 -> breakEvenHits null (write premium never repaid).
*/
/**
* The four per-1M-token USD pricing rates cacheMath reads from the TS AiModel.
* @typedef {Object} ModelRates
* @property {number|null} inputPerM Uncached prompt (input) rate, USD per 1M tokens.
* @property {number|null} outputPerM Completion (output) rate, USD per 1M tokens.
* @property {number|null} cacheReadPerM Cached prompt read rate, USD per 1M tokens.
* @property {number|null} cacheWritePerM Cache write premium rate, USD per 1M tokens.
*/
/**
* Request shape.
* @typedef {Object} CacheInput
* @property {number} promptTokens Prompt (input) tokens per request.
* @property {number} outputTokens Completion (output) tokens per request.
* @property {number} hits Requests reusing the cached prompt. Values < 1 are treated as 1.
*/
/**
* Result shape. Any missing rate nulls every field.
* @typedef {Object} CacheMath
* @property {number|null} uncached hits × (prompt·in$/M + output·out$/M) / 1e6.
* @property {number|null} cached (prompt·write$/M + hits × (prompt·read$/M + output·out$/M)) / 1e6 —
* one cache write, `hits` cache reads, output billed every request.
* @property {number|null} savings uncached − cached (negative when caching costs more).
* @property {number|null} savingsPct savings / uncached × 100; 0 when uncached is 0.
* @property {number|null} breakEvenHits ceil(write$/M / read$/M) when read$/M > 0 — cache hits needed
* for cumulative READ spend to equal ONE write premium; null otherwise.
*/
/**
* Compare uncached vs prompt-cached cost for one model.
* @param {ModelRates} model
* @param {CacheInput} input
* @returns {CacheMath}
*/
export function cacheMath(model, input) {
const { inputPerM: ipM, outputPerM: opM, cacheReadPerM: cr, cacheWritePerM: cw } = model;
if (ipM === null || opM === null || cr === null || cw === null) {
return { uncached: null, cached: null, savings: null, savingsPct: null, breakEvenHits: null };
}
const hits = Math.max(1, input.hits);
const inT = input.promptTokens;
const outT = input.outputTokens;
// One cache write, `hits` cache reads; output tokens are billed on every request.
const uncached = (hits * (inT * ipM + outT * opM)) / 1_000_000;
const cached = (inT * cw + hits * (inT * cr + outT * opM)) / 1_000_000;
const savings = uncached - cached;
const savingsPct = uncached === 0 ? 0 : (savings / uncached) * 100;
const breakEvenHits = cr > 0 ? Math.ceil(cw / cr) : null;
return { uncached, cached, savings, savingsPct, breakEvenHits };
}
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →