Cache Savings Calculator — TypeScript source
See what prompt caching saves — uncached vs cached cost over N requests, with the write-premium break-even point.
This is the TypeScript implementation — the same logic the interactive tool runs, in a shareable, citable form.
/**
* Pure cache-savings math for the Cache Savings Calculator. All rates flow
* from the model snapshot accessor (src/lib/ai/models.ts) — never hardcoded
* here. Mirrors the cost conventions of llmCost.ts (per-1M-token USD rates).
*/
import type { AiModel } from './ai/models';
export interface CacheInput {
/** Prompt (input) tokens per request. */
promptTokens: number;
/** Completion (output) tokens per request. */
outputTokens: number;
/** Requests that reuse the cached prompt. Values < 1 are treated as 1. */
hits: number;
}
export interface CacheMath {
/** hits × (prompt·in$/M + output·out$/M) / 1e6. */
uncached: number | null;
/** (prompt·write$/M + hits × (prompt·read$/M + output·out$/M)) / 1e6 —
* one cache write, `hits` cache reads, output billed every request. */
cached: number | null;
/** uncached − cached (negative when caching costs more). */
savings: number | null;
/** savings / uncached × 100; 0 when uncached is 0. */
savingsPct: number | null;
/** ceil(write$/M / read$/M) when read$/M > 0 — cache hits needed for
* cumulative READ spend to equal ONE write premium; null otherwise. */
breakEvenHits: number | null;
}
const nulled = (): CacheMath => ({
uncached: null,
cached: null,
savings: null,
savingsPct: null,
breakEvenHits: null,
});
/**
* Compare uncached vs prompt-cached cost for one model. Any missing rate
* (input, output, cacheRead, cacheWrite) makes every field null — the caller
* renders an explanatory empty state instead of partial math.
*/
export function cacheMath(model: AiModel, input: CacheInput): CacheMath {
const { inputPerM: ipM, outputPerM: opM, cacheReadPerM: cr, cacheWritePerM: cw } = model;
if (ipM === null || opM === null || cr === null || cw === null) return nulled();
const hits = Math.max(1, input.hits);
const inT = input.promptTokens;
const outT = input.outputTokens;
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 →