Direct Answer
AI inference cost is the fully allocated spend required to deliver an accepted result under a defined quality, latency, safety, and reliability contract. A defensible comparison separates hosted API charges, private-runtime total cost of ownership (TCO), and edge costs; reconciles each option to the same workload; and divides total spend by SLO-passing accepted outcomes. Token price is a useful meter, but it is not the final unit of value.
Key Takeaways
- Build a dated billing ledger because input, output, cache, batch, tool, media, region, and contract units can be priced differently.
- Compare API, self-hosted, and edge options against the same request trace, model-quality gate, and service-level objective (SLO).
- Keep fully allocated, avoidable, and marginal cost separate. Each answers a different decision.
- Treat utilization as a denominator problem: idle provisioned capacity raises unit cost, but it is not a second hardware charge.
- Route to a smaller model only after measuring false acceptance, escalation, fallback, and wasted first-pass work.
- Optimize cost per accepted outcome or business event, not cost per token in isolation.
Define the Cost Boundary Before Comparing Options
An inference-cost model is valid only when its scope, time window, workload, and acceptance rule are explicit. The same system can look cheap under marginal cost and expensive under fully allocated cost.
| Cost view | Includes | Answers |
|---|---|---|
| Fully allocated | Direct usage, allocated platform, staff, security, redundancy, review, and shared services | What does this workload cost the business? |
| Avoidable | Spend that disappears if the workload or route is removed | What can this decision actually save? |
| Marginal | Incremental spend for the next request or traffic block within available capacity | What does one more unit cost now? |
Do not use an already purchased accelerator as "free" in a TCO comparison. Its marginal cash cost may be low while its allocated cost and opportunity cost remain real. Conversely, do not charge the same hardware once as monthly depreciation and again as "idle GPU cost." Idle time reduces useful utilization and therefore increases cost per delivered unit.
The FinOps unit economics framework distinguishes resource-level metrics such as cost per token from business-value metrics such as cost per assist or resolved case. That distinction maps directly to inference systems: infrastructure meters explain spend, while accepted outcomes explain whether the spend created value.
Build a Dated API Billing Ledger
A provider price page is an input to the model, not the model itself. Official pricing pages show why a single "price per million tokens" field is insufficient: input and output can differ, prompt-cache writes and reads can differ, batch or priority modes can differ, and tools or multimodal inputs can add separate units.
Record one row for every billable dimension:
| Field | Required evidence |
|---|---|
| Service identity | Provider, exact model ID, endpoint, region, and revision |
| Usage class | Uncached input, cached input/read/write, output, reasoning, image, audio, tool, batch |
| Commercial basis | Public list, private contract, commitment, credit, currency, tax, effective date |
| Workload | Request count, token distribution, context length, output length, modality, traffic shape |
| Reliability | Timeout, retry, cancellation, failed job, duplicate side effect, fallback |
| Reconciliation | Usage export, invoice line, application event, and allocation owner |
Do not copy a permanent provider ranking into an evergreen article. Maintain rates in a dated ledger and retain the source URL. Current official references include OpenAI API pricing, Anthropic API pricing, and Gemini API pricing. Their dimensions and modifiers differ, so normalize billing columns before comparing totals.
The FinOps Open Cost and Usage Specification (FOCUS) provides a useful structure for billed cost, effective cost, commitments, credits, currency, allocation, and reconciliation. FOCUS can normalize billing records, but it does not normalize model quality, acceptance rules, or application outcomes. Add those fields in the application ledger.
Model Private-Runtime TCO Without Double Counting
Private-runtime cost is the cost of provisioned capacity plus the operating system around it. It is not simply GPU rental divided by peak benchmark throughput.
monthly_private_tco =
accelerator_rental_or_amortization
+ host_cpu_memory_and_local_storage
+ power_and_cooling
+ network_and_persistent_storage
+ orchestration_observability_and_security
+ engineering_support_and_on_call
+ evaluation_and_release_operations
+ redundancy_and_recovery_capacity
Use the same accounting horizon for every term. Amortize purchased hardware over an approved life and include the expected residual value. For rented capacity, include reserved or committed spend that is payable during idle periods. Allocate shared staff and platform costs with a documented driver such as fleet hours, requests, or accepted outcomes.
Separate capacity from accelerator telemetry
No single utilization percentage explains inference economics. Track each layer independently:
| Metric | Numerator / denominator | Decision supported |
|---|---|---|
| Fleet allocation | Assigned accelerator-hours / provisioned accelerator-hours | Capacity rightsizing |
| Accelerator activity | Busy samples / observed samples | Kernel or scheduling diagnosis |
| Memory occupancy | Allocated model and cache memory / available memory | Model placement and concurrency |
| Request goodput | Accepted SLO-passing requests / second | User-visible useful capacity |
| Token goodput | Accepted SLO-passing output tokens / second | Generation capacity under quality gates |
The economic denominator should be useful delivered work. A GPU can report high activity while requests miss time-to-first-token (TTFT), inter-token latency (ITL), or quality targets. It can also report moderate activity while the fleet is economically efficient for a bursty, strict-latency service.
The vLLM serving benchmark supports controlled request-rate, concurrency, burstiness, and goodput experiments. Its production metrics expose queue, prefill, decode, token, cache, and request signals. Pin the engine version because metric names and behavior can change.
Compare API, Self-Hosted, and Edge on One Contract
Deployment economics become comparable only after all candidates execute the same representative trace and acceptance policy.
| Boundary | Hosted API | Private runtime | Edge or on-device |
|---|---|---|---|
| Primary meter | Provider billable units | Provisioned fleet and operations | Device resources, energy, distribution, support |
| Elasticity | Provider quota and commercial tier | Autoscaling and owned capacity | Installed device fleet and runtime availability |
| Latency | Network, provider queue, prefill, decode | Local queue, prefill, decode, network | Device load, thermal state, runtime, battery policy |
| Data control | Contract, region, retention, subprocessors | Operators, backups, logs, supply chain | App permissions, telemetry, backups, model package |
| Change burden | Provider model or policy drift | Runtime, kernel, checkpoint, hardware | Device fragmentation, updates, compatibility |
| Failure cost | Rate limits, outages, retries | Capacity, preemption, on-call | Unsupported devices, thermal throttling, fallback |
Edge execution can remove some provider calls, but it does not make inference free or private by default. Include model packaging, download bandwidth, device compatibility, energy, update support, local logs, backups, telemetry, and cloud fallback. The separate small language model and edge deployment guide covers device-fit testing; the local LLM deployment guide covers runtime selection and production controls.
Use Cost per Accepted Outcome as the Decision Metric
Cost per accepted outcome prevents low-quality attempts from masquerading as savings. Define an acceptance rule before testing a model, route, cache, or prompt.
cost_per_accepted_outcome =
(provider_cost
+ private_runtime_cost
+ edge_cost
+ retry_and_fallback_cost
+ human_review_cost
+ allocated_operations_cost)
/ accepted_outcomes
An accepted outcome must pass the workload's measurable contract. Examples include a support case resolved without reopening, a code change passing tests and review, an extraction matching labeled fields, or an agent action completing without an unauthorized side effect.
For high-risk workflows, cost is subordinate to release gates. The NIST AI Risk Management Framework provides a risk-management structure for trustworthiness considerations. It does not prescribe an inference price formula, but it supports keeping validity, safety, privacy, security, transparency, and accountability inside the decision rather than optimizing them away.
Evaluate Small Models and Routing as a System
A smaller model reduces cost only when the complete route remains acceptable. Parameter count is not a quality contract, and a narrow benchmark win does not prove broad replacement.
For each task slice, measure:
- first-pass acceptance and false acceptance;
- escalation rate and escalation reason;
- fallback latency and fallback success;
- tokens and compute spent before fallback;
- tool-call schema validity and side-effect correctness;
- refusal, policy, and authorization behavior;
- model-package, evaluation, and maintenance cost.
Let p_small_accept be the share of requests correctly accepted by the small route, p_escalate the share sent to a larger route, and p_false_accept the share incorrectly accepted. A simple expected-cost view is:
expected_route_cost =
small_route_cost
+ p_escalate * fallback_cost
+ p_false_accept * correction_and_risk_cost
The formula is incomplete without quality gates: a route that lowers expected spend but exceeds the false-acceptance or safety budget must not ship. Test deterministic rules as a candidate too. Classification, validation, retrieval, or templates may cost less and fail more predictably than any generative model.
Run a Reproducible Sensitivity Model
A sensitivity model should emit both assumptions and results so reviewers can reproduce the crossover. The script below compares monthly API cost with fully allocated private-runtime TCO and reports cost per accepted outcome. It deliberately accepts rates and performance as inputs instead of embedding vendor prices or benchmark claims.
from __future__ import annotations
import argparse
import json
from dataclasses import asdict, dataclass
@dataclass(frozen=True)
class Scenario:
monthly_requests: int
input_tokens_per_request: int
output_tokens_per_request: int
api_input_per_million: float
api_output_per_million: float
api_extra_monthly: float
private_fixed_monthly: float
private_variable_per_request: float
api_acceptance_rate: float
private_acceptance_rate: float
api_retry_multiplier: float
private_retry_multiplier: float
def probability(value: float, name: str) -> float:
if not 0 < value <= 1:
raise ValueError(f"{name} must be in (0, 1]")
return value
def nonnegative(value: float, name: str) -> float:
if value < 0:
raise ValueError(f"{name} must be nonnegative")
return value
def evaluate(s: Scenario) -> dict[str, float]:
if s.monthly_requests <= 0:
raise ValueError("monthly_requests must be positive")
for name in (
"input_tokens_per_request",
"output_tokens_per_request",
"api_input_per_million",
"api_output_per_million",
"api_extra_monthly",
"private_fixed_monthly",
"private_variable_per_request",
):
nonnegative(float(getattr(s, name)), name)
probability(s.api_acceptance_rate, "api_acceptance_rate")
probability(s.private_acceptance_rate, "private_acceptance_rate")
if s.api_retry_multiplier < 1 or s.private_retry_multiplier < 1:
raise ValueError("retry multipliers must be at least 1")
api_attempts = s.monthly_requests * s.api_retry_multiplier
private_attempts = s.monthly_requests * s.private_retry_multiplier
api_token_cost = (
api_attempts
* (
s.input_tokens_per_request * s.api_input_per_million
+ s.output_tokens_per_request * s.api_output_per_million
)
/ 1_000_000
)
api_total = api_token_cost + s.api_extra_monthly
private_total = (
s.private_fixed_monthly
+ private_attempts * s.private_variable_per_request
)
api_accepted = s.monthly_requests * s.api_acceptance_rate
private_accepted = s.monthly_requests * s.private_acceptance_rate
return {
"api_monthly_cost": api_total,
"private_monthly_cost": private_total,
"api_cost_per_accepted_outcome": api_total / api_accepted,
"private_cost_per_accepted_outcome": private_total / private_accepted,
}
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("scenario", help="Path to a JSON scenario")
args = parser.parse_args()
with open(args.scenario, encoding="utf-8") as handle:
scenario = Scenario(**json.load(handle))
print(json.dumps({
"assumptions": asdict(scenario),
"results": evaluate(scenario),
}, indent=2))
if __name__ == "__main__":
main()
Save assumptions separately:
{
"monthly_requests": 1000000,
"input_tokens_per_request": 800,
"output_tokens_per_request": 200,
"api_input_per_million": 1.0,
"api_output_per_million": 4.0,
"api_extra_monthly": 500.0,
"private_fixed_monthly": 3500.0,
"private_variable_per_request": 0.0002,
"api_acceptance_rate": 0.92,
"private_acceptance_rate": 0.88,
"api_retry_multiplier": 1.03,
"private_retry_multiplier": 1.08
}
Run python inference_cost.py scenario.json, then vary one assumption at a time. Replace every illustrative input with the dated contract, invoice, benchmark, and acceptance result for your workload. Add low, base, and high scenarios for demand, token mix, useful utilization, acceptance, retries, staffing, power, exchange rate, and required replicas.
Test Cost Optimizations Behind Quality Gates
Cost levers change different parts of the system and should not share one savings claim.
Prompt and KV caching
Prompt caching can reduce repeated input processing under provider-specific rules. A serving KV cache reduces repeated attention-state computation within or across eligible requests. Semantic caching reuses an answer based on meaning. These are different mechanisms with different identity, freshness, isolation, and invalidation risks.
Measure eligible-request rate, hit rate, write/read charges, false reuse, stale reuse, latency, storage, invalidation, and quality. The semantic caching production guide covers authorization and false-hit controls.
Batching and scheduling
Continuous batching can improve delivered capacity by scheduling requests as slots become available. Offline provider batches may use a different commercial rate. Both can increase queueing or cancellation complexity, so measure TTFT, ITL, end-to-end latency, completion rate, and goodput rather than quoting peak tokens per second.
Quantization and model compression
Quantization can reduce weight memory and sometimes improve throughput, but kernel support, calibration, context, hardware, and task quality determine the result. Benchmark the exact artifact and runtime. Include any acceptance loss or fallback work in outcome cost. The model quantization guide explains those boundaries.
Context selection and output control
Reducing irrelevant context and constraining output can lower billable or computed tokens. Validate citation coverage, instruction retention, refusal behavior, schema validity, and answer quality. A smaller prompt that causes retries can increase total cost.
Reconcile Spend to Application Events
Cost observability should join billing, runtime, and outcome evidence without retaining unnecessary sensitive content.
event_id
request_id
workload_class
tenant_id_hash
model_and_revision
route_and_fallback_reason
input_output_cache_and_tool_units
queue_ttft_itl_and_e2e
retry_and_attempt_count
quality_gate_version
accepted_outcome
billed_cost
allocated_runtime_cost
Reconcile three totals every period:
- Provider usage to provider invoice.
- Runtime allocation to infrastructure and platform ledgers.
- Application events to accepted business outcomes.
Record completeness, late-arriving events, currencies, credits, and shared-cost allocation. Hashing a tenant identifier does not automatically make all traces safe: redact prompts, secrets, personal data, tool payloads, and generated content according to a documented retention purpose.
Decision Gates and Failure Modes
A cost change is ready only when it passes accounting, quality, service, and rollback gates.
- Baseline: Freeze a representative trace, acceptance rubric, SLO, model identity, and dated cost ledger.
- Capacity test: Sweep request rate, concurrency, context, output length, and burstiness. Report goodput and failures, not peak throughput alone.
- Quality test: Compare slices, false acceptance, escalation, recovery, safety, and human review.
- Sensitivity test: Vary demand, utilization, replicas, prices, staffing, power, retry rate, and acceptance.
- Release gate: Set budget, quality, and SLO thresholds with an owner, rollback trigger, and fallback capacity.
- Reconciliation: Compare forecast with invoice, infrastructure ledger, and accepted outcomes after release.
Common failures include comparing different model quality, using average traffic to size burst capacity, treating list price as invoice cost, counting peak throughput as useful capacity, excluding failed work, and declaring local execution private without auditing logs, updates, backups, and operators.
Frequently Asked Questions
How do you calculate AI inference cost?
Choose a cost boundary and time window, build a dated usage ledger, allocate provider or runtime TCO, add retries, failures, review, observability, and shared services, then divide by accepted outcomes. Keep cost per token as a diagnostic submetric.
When is self-hosting cheaper than an API?
There is no universal request or token threshold. Self-hosting wins only when its fully allocated cost per accepted outcome is lower for the same quality, SLO, reliability, and risk contract. Run a sensitivity model because traffic shape, replicas, utilization, hardware price, and staffing can reverse the result.
Can a small model reduce inference cost?
Yes, for a verified task slice. Evaluate the complete route, including classifier errors, false acceptance, escalation, fallback, wasted first-pass work, maintenance, and safety. Do not infer suitability from parameter count alone.
Is high GPU utilization always cheaper?
No. High accelerator activity can coexist with queueing, missed latency targets, or rejected outputs. Economic efficiency depends on accepted SLO-passing work per provisioned dollar, while activity and memory metrics help diagnose why capacity is or is not useful.
Should provider prices appear in a permanent comparison table?
Keep exact rates in a dated ledger or generated report. In the article, document the billing dimensions, source URLs, and update process. This preserves the decision method when providers change models, cache rules, regions, discounts, or tool pricing.
References
- FinOps Unit Economics
- FOCUS Specification
- OpenAI API Pricing
- Anthropic API Pricing
- Gemini API Pricing
- vLLM Serving Benchmark
- vLLM Production Metrics
- NIST AI Risk Management Framework