---
title: How cost accounting works
description: Token-accurate, multi-dimensional metering — how the platform knows the true cost of one published article, and what that number changes.
locale: en
version: 0.2.0
canonical: https://enterium-developer-docs.pages.dev/developers/how-it-works/cost-accounting/
---

> Documentation index: https://enterium-developer-docs.pages.dev/developers/llms.txt — every page of this portal has a Markdown twin at <route>.md; the frozen API contract is at https://enterium-developer-docs.pages.dev/developers/api/openapi.json.

**The problem:** an LLM platform's unit economics live or die on one
number — *what does one published article actually cost?* — and that
number is surprisingly hard to get. Flat per-call estimates drift from
reality (here, a flat constant once under-counted the platform's dominant
cost driver by ~6×); provider dashboards aggregate by account, not by
article.

## Layer 1 — the immutable usage event

Every run emits one immutable **usage event** — broken down by model, with per-step token deltas kept alongside the run — carrying the full
attribution vector: tenant, contract, record, pipeline, step, model,
token counts, timestamp. Not a log line — a queryable ledger row. Nothing
about cost is derived at call time; events store *facts* (tokens, model),
and money is computed later.

```mermaid
flowchart LR
    CALL[LLM call] --> UE[(usage_event<br/>tokens · model · contract ·<br/>pipeline · step · time)]
    PB[Versioned pricebook] --> COST[Cost queries]
    UE --> COST
    COST --> A[Cost per article]
    COST --> B[Cost per contract / day]
    COST --> C[Reconciliation vs provider invoice]
```

## Layer 2 — the versioned pricebook

Prices change; history must not. Cost is computed by joining events against
a **versioned pricebook** — the price valid *at event time* — so last
month's numbers stay true after a provider reprices. The same join
reconciles the computed total against the provider's actual invoice: if
the ledger and the bill diverge, something is unmetered, and that is a
defect, not a rounding note.

## Layer 3 — the cost of one article, amortized

"Cost per article" includes more than its Generate run: Collect research
that fed it is amortized across the articles it enabled. This is the number
the platform actually steers by — it exposed, for example, that a period of
post-gate rejects multiplied the *effective* cost per published article
several-fold even though per-call prices never moved. Without per-article
attribution that regression is invisible inside a monthly total.

## Layer 4 — budgets (designed, not yet armed)

Metering is meant to feed enforcement: per-run budgets with a watcher that
would stop a breaching tenant's runs through the run control channel.
The enforcement stage is not enabled yet: no budgets are configured, and
the control channel the watcher would use is the one the
[run engine](../run-engine/#trade-offs) documents as not interrupting a
run mid-flight. There is deliberately **no automatic provider-level kill
switch** either — an automatic billing cut-off takes production down with
the runaway it was meant to stop — so the working control today is a
daily spend-anomaly signal in the nightly report: it notifies the owner,
and a human decides. This page will change when budgets are configured
and the watcher is measured.

## Trade-offs

Metering every call costs a write per call and a discipline: any new LLM
call path must emit the event, and the reconciliation check exists
precisely to catch paths that forget. Amortization rules are a modeling
choice — the platform records the raw vectors so the model can be changed
retroactively without losing data. Absolute figures — per article, per
night, per month — are deliberately not published on this portal: the
mechanism is public, the ledger is not.

## See it in two minutes

The `metering` domain in `list_domains` exposes the read surface; per-run
costs appear in run reports.
