The safest practical approach is to reconstruct immutable usage events rather than add charges directly. Give every event a stable idempotency key, enforce uniqueness at the durable database boundary, and check usage and settlement records independently. Run a dry-run classification first, then permit rating only for events whose identity, inputs, and charge eligibility can be verified. Keep settled records immutable and handle necessary corrections through explicit adjustments.
The short answer: reconstruct usage first, then determine charge eligibility
A usage backfill should restore the metering history without assuming that every missing event represents unpaid consumption. That distinction matters because a request may be absent from the usage store yet already appear on an invoice, in a settlement record, or in another downstream accounting system.
The backfill therefore has two separate jobs:
- Reconstruct the usage event. Restore what happened using deterministic identity and metering inputs.
- Determine financial eligibility. Decide whether that event may be rated, invoiced, adjusted, or recorded as already settled.
Do not combine these decisions into a blind insert-and-charge operation. The safer pattern is to send reconstructed events through the same idempotent ingestion controls used for ordinary usage wherever feasible. Direct invoice edits and unguarded table inserts can bypass duplicate detection, lifecycle checks, and audit records.
Why a missing usage event does not necessarily mean an unpaid request
Usage accounting usually involves several related but distinct states:
| State | Question it answers | Backfill implication |
|---|---|---|
| Usage capture | Was the request or metering event recorded? | A missing event may need reconstruction. |
| Rating | Were metering units evaluated under a specific price and currency? | Rating should occur only with deterministic inputs and verified eligibility. |
| Invoicing | Was the rated amount included on an invoice or equivalent billing document? | Existing invoice treatment must be checked before creating a new financial effect. |
| Settlement | Was the relevant charge finalized or paid? | A settled request, line item, or period should not be charged again or silently mutated. |
These states can diverge after queue failures, delayed exports, partial database writes, migration errors, or retries. For example, an invoice line may have been created from an intermediate usage stream even though the durable usage record is now missing. Recreating the event is appropriate for historical completeness, but rerating it as new consumption could cause a duplicate charge.
Before writing anything, query both sides of the workflow:
- Does a usage event already exist under the same stable identity?
- Is there an invoice line, settlement reference, or adjustment tied to that request or event?
- Is the associated billing period open, closed, or settled?
- Do the reconstructed metering and pricing inputs agree with existing records?
Event presence should never serve as the sole proxy for payment status.
Why durable idempotency is safer than relying on exactly-once delivery
Exactly-once delivery is difficult to guarantee across logs, queues, databases, rating services, and invoicing systems. Network timeouts can leave a caller uncertain whether a write succeeded, while workers may retry after partial failure. A queue can also redeliver a message that was processed successfully.
A more practical pattern combines at-least-once processing with several durable controls:
- A stable idempotency key derived from request or usage identity
- A database-enforced uniqueness constraint at the authoritative write boundary
- Deterministic comparison of repeated payloads
- Separate checks for usage, invoice, and settlement state
- Transactional writes or an equivalent atomic boundary
- Retry-safe downstream processing
- Post-run reconciliation and compensating actions
An in-memory cache can reduce duplicate work, but it should not be the only duplicate-charge control. Caches expire, restart, and may not be shared consistently across workers. The authoritative uniqueness decision should survive process restarts and concurrent attempts.
A duplicate-key result also needs interpretation. If the existing event and incoming event have the same identity and equivalent payload, the retry can be treated as already applied. If they share an identity but contain different tenant, model, units, period, or pricing data, classify the record as a conflict rather than overwriting it.
Define event identity and billing states before running the backfill
Backfill safety begins before the job runs. Define which fields identify an event, which fields determine its rating, and which systems are authoritative for settlement. Upstream logs should be treated as reconstruction inputs—not automatically as complete, unique, ordered, or financially authoritative records.
Build a stable idempotency key from request and usage identity
Use an identifier that remains stable across retries, exports, and replay jobs. A source request ID or original usage-event ID is preferable when it is globally unique within a known namespace. If it is only unique within a tenant or source, combine it with that scope.
An illustrative identity could be:
``text idempotency_key = hash( tenant_id + source_system + stable_request_id + event_kind ) ``
The exact composition depends on whether one request can produce multiple legitimate usage events. If a request emits separate input-token, output-token, image, audio, or tool-use records, include a stable event kind or sequence identifier so those events do not collide.
Do not use a timestamp by itself. Two requests can share a timestamp, and the same request may acquire different timestamps as it moves through services. Avoid including mutable rating results in the identity as well; otherwise, rerating the same event could create a new key and defeat deduplication.
At the durable boundary, enforce uniqueness rather than relying only on an application-level lookup:
``sql CREATE TABLE usage_event ( idempotency_key TEXT PRIMARY KEY, tenant_id TEXT NOT NULL, source_request_id TEXT NOT NULL, service_id TEXT NOT NULL, usage_period_start TIMESTAMP NOT NULL, metering_units DECIMAL NOT NULL, pricing_version TEXT NOT NULL, currency TEXT, payload_hash TEXT NOT NULL, reconstruction_job_id TEXT, charge_eligible BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMP NOT NULL ); ``
This is a minimal vendor-neutral example, not a universal billing schema. Production designs may separate raw events, normalized usage, rating decisions, and accounting entries into different stores.
Preserve the inputs needed for deterministic rating
A backfilled event should carry enough information for another worker—or a later audit—to reach the same interpretation. Useful inputs commonly include:
- Tenant or account identity
- Stable request or usage-event ID
- Source system and event kind
- Model, endpoint, or service identity
- Usage period and metering units
- Pricing version or rate-plan reference
- Currency, where monetary rating applies
- Source record reference and normalized payload hash
Preserving a pricing version is particularly important. Applying today’s price to historical consumption can produce a different amount from the price applicable during the original usage period. If the historical pricing input cannot be established, the event should be classified as unverifiable rather than rated speculatively.
Normalization should also be deterministic. For example, the job should not alternately round units before and after aggregation depending on which worker handles the event. Define unit conversion, precision, time-zone treatment, and period boundaries before comparing totals.
Separate capture, rating, invoicing, and settlement states
Model financial effects as explicit state transitions rather than side effects of event insertion. A reconstructed event can exist while remaining ineligible for charging. That is useful when restoring telemetry for an already-settled request or when preserving an event that requires manual review.
A conservative decision flow is:
- Derive the stable identity and normalized payload.
- Look for an existing usage event under that identity.
- Look for invoice and settlement records using available request, event, line-item, and period references.
- Compare the reconstructed payload with any existing records.
- Classify the candidate before enabling writes.
- Insert through the normal idempotent ingestion path where feasible.
- Set charge eligibility only after all relevant checks succeed.
A dry run should classify every candidate and propose an action:
| Classification | Meaning | Permitted next action |
|---|---|---|
| Missing | No matching usage, invoice, or settlement record was found, and required inputs are verifiable. | Insert idempotently; evaluate rating eligibility under normal controls. |
| Already present | An equivalent usage event already exists. | Do not insert or rerate; record the no-op result. |
| Already settled | The usage event is missing, but a matching settled financial record exists. | Reconstruct only if operationally needed, mark it non-chargeable, and link the settlement reference. |
| Conflicting | The same identity exists with materially different fields or totals. | Quarantine for review; do not overwrite or charge. |
| Unverifiable | Identity, units, pricing version, or settlement relationship cannot be established. | Preserve the candidate for investigation; do not create a financial effect. |
If a settled invoice or closed period needs correction, avoid rewriting the original record in place. Use an explicit debit or credit adjustment tied to the original line, with the accounting treatment reviewed by the organization responsible for the billing system.
Illustrative retry-safe backfill logic
The following pseudocode shows the control flow without assuming a particular vendor or billing platform:
```text for candidate in bounded_batch: event = normalize(candidate) key = derive_stable_identity(event)
usage = find_usage_by_key(key) financial = find_invoice_or_settlement(event)
decision = classify(event, usage, financial) write_audit(job_id, key, decision, source=candidate)
if decision == ALREADY_PRESENT: continue
if decision in [CONFLICTING, UNVERIFIABLE]: quarantine(event, decision) continue
begin_transaction()
inserted = insert_usage_if_absent( key=key, event=event, charge_eligible=false )
if inserted and decision == MISSING: mark_charge_eligible_if_period_open_and_unbilled(key)
if inserted and decision == ALREADY_SETTLED: attach_settlement_reference(key, financial.reference)
append_backfill_result(job_id, key, decision) commit_transaction() ```
The transaction should cover the event insertion and its local charge-eligibility decision. If billing spans separate systems that cannot share a transaction, use an equivalent durable pattern such as an outbox, an idempotent command, and a recorded downstream result. Transactions and queues reduce failure windows, but neither alone guarantees exactly-once charging.
Protect settled records and make corrections explicit
Once a period or line item is settled, backfill logic should treat it as immutable. This prevents an operational telemetry repair from silently changing a completed financial record.
When a correction is genuinely necessary, create a separate adjustment containing:
- A reference to the original invoice line or settlement record
- The reason for the correction
- The amount and currency, where applicable
- The pricing and usage inputs used to calculate it
- The approving operator or workflow
- The originating backfill job and timestamp
This append-only approach preserves the original history and makes the correction visible. It also supports reversal through a compensating entry rather than destructive rollback.
Run bounded batches, reconcile totals, and monitor the result
Start with a dry run over a representative sample. Review classification counts and monetary projections before enabling writes. During execution, use bounded batches and save checkpoints so a failed worker can resume without replaying the entire population.
A practical implementation checklist includes:
- Freeze the identity, normalization, and historical pricing rules for the run.
- Record the source range, query, snapshot, or export used to generate candidates.
- Complete a dry run and review missing, present, settled, conflicting, and unverifiable counts.
- Require approval before changing from dry-run to write mode.
- Use the normal idempotent ingestion path where feasible.
- Enforce uniqueness in the database and handle duplicate-key results as expected outcomes.
- Limit concurrent workers when they can touch the same tenants, periods, or identifiers.
- Commit in bounded batches and save durable checkpoints.
- Make every retry safe after a timeout or partial failure.
- Maintain a compensating-action plan for unintended downstream entries.
- Compare event counts, rated units, and monetary totals before and after the run.
- Monitor duplicate-key conflicts, quarantined records, and unexpected charge creation.
The audit trail should be append-only and include the source data reference, backfill job ID, event identity, timestamps, classification, decision reason, result, and operator approval. Retain both no-op and rejected decisions; they demonstrate why a candidate did not create a new charge.
Reconciliation should occur at more than one level. Compare totals by tenant, service or model, usage period, metering unit, pricing version, and currency where applicable. Aggregate totals may balance even when individual customers or periods are wrong, so investigate both global and segmented differences.
Applying these controls to enterprise LLM inference operations
LLM inference metering can involve managed API usage, private model serving, caching, routing, batching, quantization, and GPU scheduling. These serving-layer decisions can affect which telemetry is generated and how usage must be normalized before it reaches a separate rating or billing workflow.
Token Forge Cloud’s Managed Model APIs provide an API-first path for model access and usage data, while Token Forge Cloud Private LLM Inference focuses on private deployment and serving-layer optimization for enterprise workloads. When organizations connect inference telemetry to their own financial systems, they should define stable request identities, normalization rules, and settlement checks across that integration.
The billing ledger, settlement process, adjustment policy, and backfill controls should be validated within the organization’s selected metering and accounting architecture. The vendor-neutral pattern in this guide can help teams frame that design without treating serving telemetry alone as proof that a request is unpaid.
Contact Token Forge Cloud to discuss API access, private deployment, and LLM inference cost control.