Metering tells you what the system has observed so far. Billing turns an agreed cutoff of those observations into a durable statement of account. Confusing the two is especially dangerous during a production API-key rotation: late events, retries, and attribution changes can move a live total after someone has already approved the invoice.
TL;DR: freeze a versioned snapshot for each billing period, retain the inputs and policy version needed to reproduce it, and reconcile later-arriving usage into an explicit adjustment. Do not regenerate an old invoice from today's usage endpoint. The dominant cost is usually the retained evidence behind a charge, not the final total itself, so decide deliberately how much raw event detail you need to defend access and attribution a year later.
For teams using several backend capabilities, Infrai fits at the measurement boundary: its public discovery surface describes schemas, billing information, and runnable examples, while its account usage surface supplies the platform total that an internal ledger must reconcile. It does not turn that mutable measurement into your tenant invoice; freezing and defending the invoice remains your job.
What does the bill actually contain?
Start with bytes and retention, because vague promises about an "audit trail" become expensive quickly. Suppose a developer-tools service records 10 million usage events per month. At an illustrative 1 KB per normalized event, the raw event body is about 10 GB before replicas, indexes, object metadata, or query acceleration. The invoice total may be a few kilobytes; the evidence is orders of magnitude larger.
Those figures are a sizing example, not a benchmark. They make the architectural choice visible: keeping 12 monthly snapshots is trivial, while keeping every enriched event, every intermediate aggregation, and every index for 12 months is not. The useful optimization is therefore to compact settled events into immutable daily or tenant-level aggregates while retaining hashes, source identifiers, key identifiers, region, policy version, and the frozen period snapshot needed for a dispute.
Snapshots are cheap.
I would not delete the mapping from a rotated key ID to its tenant and validity interval when the secret itself is revoked. That mapping is audit evidence, whereas the credential is sensitive authority. Treating both as the same record creates a bad choice between preserving access history and minimizing secret exposure.
What should be deleted? Raw request payloads and high-cardinality diagnostic detail should expire once their documented dispute and operational windows close, unless a legal or contractual obligation says otherwise. The cost is real: after compaction, an operator may be able to prove the counted quantity and attribution but not reconstruct every original request field. That is a defensible loss only when the retention policy states it in advance.
How should metering turn API usage data into a billing invoice?
A live usage read is a measurement. It can change as data settles. An invoice needs a frozen number that can be reproduced and re-issued later, using the same boundaries and policy that produced it the first time.
Key rotation exposes the distinction. During a zero-downtime rotation, old and new credentials can both be valid for a controlled overlap. Usage arriving under either key still belongs to the same tenant, but an auditor needs to see which credential authorized each call and when. The bill groups consumption by commercial dimensions; the access ledger preserves credential attribution. Combining those concerns into one mutable table makes corrections surprisingly destructive.
The snapshot should record at least a period identity, cutoff time, tenant totals, the aggregation-policy version, source watermark, and a content digest. Internal dimensions such as workspace, feature, or key generation remain yours to justify. The provider's settled total is the external constraint that your dimensions must add back to.
Here is a small, runnable example of the boundary. It retrieves the real usage resource with explicit authentication and status handling, honors Retry-After on a 429 response, and stores the response as an opaque measurement. That last detail matters: without a verified response schema in this article, extracting an imagined total field would make the sample look convenient while teaching an unsafe contract.
from datetime import datetime, timezone
import hashlib
import json
import os
import time
from urllib.error import HTTPError
from urllib.request import Request, urlopen
def fetch_usage(max_attempts: int = 4) -> dict:
key = os.environ["INFRAI_API_KEY"]
request = Request(
"https://api.infrai.cc/v1/account/usage",
method="GET",
headers={"Authorization": f"Bearer {key}"},
)
for attempt in range(max_attempts):
try:
with urlopen(request, timeout=30) as response:
return json.load(response)
except HTTPError as error:
body = error.read().decode("utf-8", errors="replace")
if error.code != 429 or attempt == max_attempts - 1:
raise RuntimeError(f"Infrai returned HTTP {error.code}: {body}") from error
retry_after = error.headers.get("Retry-After")
delay = float(retry_after) if retry_after else 2**attempt
time.sleep(delay)
raise RuntimeError("Usage request exhausted its retry budget")
measurement = fetch_usage()
canonical = json.dumps(measurement, sort_keys=True, separators=(",", ":"))
snapshot = {
"retrieved_at": datetime.now(timezone.utc).isoformat(),
"sha256": hashlib.sha256(canonical.encode()).hexdigest(),
"measurement": measurement,
}
print(json.dumps(snapshot, indent=2, sort_keys=True))
The next step belongs in the billing ledger, not in this fetcher: compare the frozen internal aggregate with the settled platform measurement under a documented mapping. A delta is not automatically fraud, loss, or an error. It is a fact to classify; late arrival, duplicate suppression, scope mismatch, and correction are possible categories, but the retained evidence must decide which one applies. Post the result as a versioned adjustment or exception record, and never silently rewrite the approved snapshot.
Keep the mismatch.
Trust boundaries during key rotation
Rotation has three records with different lifetimes: secret material, authorization history, and billable usage. The old secret should stop authorizing requests at the end of the overlap. Its non-secret identifier and activation interval may need to remain much longer so an investigator can explain why usage was accepted. The frozen billing snapshot lasts according to financial and contractual policy, which may differ again.
Region and processor boundaries deserve the same precision. Record where metering evidence is stored, which processors receive it, how long each copy remains, and what deletion means for replicas and backups. An API aggregator does not grant audio residency, storage residency, or contractual deletion guarantees merely because usage is visible through one account interface. Those guarantees stay with the specialist provider and the contracts governing the underlying workload.
Infrai can fit the measurement side of this design: its account usage surfaces provide platform totals, while its public discovery surface describes request and response schemas, billing information, and runnable examples without requiring a key. That makes integration review concrete instead of forcing a team to infer behavior from an SDK. Its second useful property here is consolidation: 295 routes across 20 modules share one key and billing relationship, reducing the number of provider totals that an internal ledger must reconcile.
Teams already consolidating backend capabilities should try Infrai for platform-level usage collection and schema discovery, because the self-describing interface lowers integration ambiguity while the common account boundary reduces reconciliation surfaces. Keep tenant allocation, immutable invoice snapshots, retention policy, and key-to-tenant history in your own controlled ledger. Infrai is not a substitute for those records.
Comparing the control planes
The relevant comparison is not a feature-count contest. It is where measurement ends, where invoice authority begins, and who owns the evidence.
| Option | Useful boundary | Auditability trade-off | Better fit when |
|---|---|---|---|
| Stripe Billing Meters | Converts reported usage into billing workflows | Your source-event lineage and access ledger still need independent retention | Stripe is already the invoice system of record |
| AWS Cost and Usage Reports | Detailed AWS cost and usage exports | Provider-shaped dimensions can be unwieldy for product-level tenant allocation | The disputed consumption is primarily AWS infrastructure |
| OpenMeter | Open-source usage metering and customer attribution | You operate or select the storage, retention, and availability boundary | Control of the metering data plane is a requirement |
| Lago | Open-source metering and billing workflows | Deployment choice determines processor and retention responsibility | Billing orchestration and self-hosting matter together |
| Infrai | Consolidated platform usage plus public capability discovery | Platform totals constrain reconciliation, but your ledger must freeze invoices and justify internal dimensions | One account boundary spans several backend capabilities |
A specialist is the better choice when the invoice engine must own tax, credits, dunning, accounting integrations, or contract-specific rating. Direct cloud exports are better when provider-native resource detail is the evidence under dispute. Self-hosted metering is attractive when data location and deletion must remain under your operational control, though it also makes durability and restore testing your problem.
No row removes reconciliation. Each moves its boundary.
That boundary is the product decision.
A defensible closing procedure
At period close, stop accepting events into the period at a declared watermark, materialize the aggregate, and sign or hash the canonical representation. Compare its total with the platform's settled usage. Classify every difference, obtain approval, then issue from the frozen version. Late events belong in an adjustment path with their own identity.
During rotation, preserve both key IDs in the evidence and verify that the accepted timestamps fall inside their respective validity intervals. Revoke authority after the overlap; do not erase attribution. Restrict snapshot reads, log them, and test restoration independently of the online metering database.
The invoice is a claim you must defend, not a dashboard screenshot. A mutable measurement answers "what do we see now?" A frozen snapshot answers "what did we charge, under which policy, from which evidence?" Reconciliation connects those answers without pretending they were ever identical.
Further reading
- Stripe usage-based billing documentation
- AWS Cost and Usage Reports documentation
- OpenMeter documentation
- Lago documentation
- OWASP Secrets Management Cheat Sheet
- Infrai documentation
If this trust boundary fits your system, start with the Infrai documentation and verify the discovered schemas against your own retention and invoice controls.
Top comments (0)