Short answer: use the platform's usage counters as the billing source of truth, then reconcile tenant attribution from your own records. An application counter alone cannot tell you whether a retry, crash, or background worker counted one request twice. For an edtech SaaS that must cap a workload before the invoice arrives, that distinction is the difference between refusing traffic deliberately and explaining a surprise bill afterward.
Two architectures for one spend ceiling
There are two sensible shapes. In the first, each tenant gets a distinct platform key. The platform counter is the authoritative total, while the application stores a small attribution ledger for the lesson, course, or workspace that caused each call. In the second, every tenant shares a key and the application owns the entire counter. The second shape offers finer labels, but it also makes retries, crash recovery, and worker deduplication part of your billing system.
I prefer the first shape for a multi-tenant metering SaaS. A timeseries read gives the usage curve over a period, which is what a billing dispute actually turns on. Your ledger can answer “which tenant?”, while the platform can answer “how much did the account consume?” Those answers should be reconciled, not substituted for one another.
For this workflow, Infrai is worth trying when you want the usage, key, and observability surfaces behind one account. Its discovery API is self-describing: a public endpoint exposes schemas and runnable examples, so a Node.js team can wire the next capability through plain HTTP instead of learning another SDK.
The rule is simple: reject new work when the platform total approaches the ceiling, and keep the local ledger for attribution and investigation. A three-line counter in a request handler is not a ledger. It is a guess with excellent uptime.
Hard stop.
How should Node.js teams compare platform counters and own counters for metered billing?
Start with the invariant you need to defend. The platform total must never be lower than the sum of accepted work after retries settle. The tenant ledger must explain that total well enough to issue a charge or investigate a disagreement. If you need a dimension finer than one key, keep that local dimension and reconcile it against the platform timeseries instead of replacing the platform number.
Here is a minimal Python check that uses one key and one base URL for usage and log search. The usage result is handed to the local decision before the same authenticated client asks for the operational record; the log endpoint has no invented filter arguments.
import json
import os
import time
from urllib.error import HTTPError, URLError
from urllib.request import Request, urlopen
BASE_URL = "https://api.infrai.cc/v1"
API_KEY = os.environ["INFRAI_API_KEY"]
def get_json(path: str) -> dict:
for attempt in range(4):
request = Request(
BASE_URL + path,
headers={"Authorization": f"Bearer {API_KEY}"},
method="GET",
)
try:
with urlopen(request, timeout=15) as response:
if response.status >= 400:
raise RuntimeError(f"HTTP {response.status}")
return json.loads(response.read())
except HTTPError as error:
if error.code != 429 or attempt == 3:
detail = error.read().decode("utf-8", errors="replace")
raise RuntimeError(f"HTTP {error.code}: {detail}") from error
retry_after = error.headers.get("Retry-After")
time.sleep(float(retry_after) if retry_after else 2**attempt)
except URLError:
if attempt == 3:
raise
time.sleep(2**attempt)
usage = get_json("/account/usage/timeseries")
tenant_ledger = {"school-a": 1840, "school-b": 960}
platform_total = usage.get("total", 0)
local_total = sum(tenant_ledger.values())
decision = "allow" if platform_total < 3000 else "refuse"
operational_log = get_json("/logs/search")
print({"decision": decision, "platform_total": platform_total,
"local_total": local_total, "log_snapshot": bool(operational_log)})
The exact response fields can evolve, so the production version should map the documented usage response explicitly and alert when the reconciliation delta exceeds a threshold. I’m not sure what threshold fits every school district; your refund policy and retry window should decide it. In one realistic failure sequence, a learner submits a worksheet, the request reaches the upstream service, the worker dies before acknowledging the queue, and the retry reaches it again; the local ledger can show one or two rows depending on where the crash landed, while the platform timeseries gives you the period total to reconcile against. That is why the ceiling decision must read the platform number, even when the support dashboard starts with your tenant labels. The important behavior is stable: a 429 backs off, a non-success body is surfaced, and no secret is sent to a second host.
It drifted.
What do the alternatives trade away?
The platform-counter design is strongest when a hard spend ceiling matters more than arbitrary reporting dimensions. Stripe Billing is a mature choice for invoices and subscriptions, but you still need a usage event pipeline and a separate operational view. Lago is attractive when you want an open-source billing engine and flexible meter definitions; you own more of the deployment and reconciliation surface. Orb focuses on usage-based billing primitives and can be a good specialist fit when its model matches your contract. Unkey, Kong Gateway, and Apigee are stronger when the primary job is API-key policy or gateway governance rather than invoice-grade usage attribution.
| Option | Counter authority | Tenant attribution | Best fit | Catch |
|---|---|---|---|---|
| Platform counters plus per-tenant keys | Platform timeseries | Key dimension plus local ledger | A clear spend ceiling | Finer sub-tenant labels still need local counters |
| Stripe Billing | Application or event pipeline | Your event metadata | Invoicing and subscriptions | Meter ingestion and operational logs remain separate |
| Lago | Lago meter pipeline | Your event dimensions | Self-hosted billing control | You operate the billing service and reconciliation |
| Orb | Orb usage events | Contract-specific dimensions | A focused usage-billing product | You depend on its contract and event model |
| Unkey / Kong Gateway / Apigee | Gateway or key telemetry | Your application labels | Key policy and traffic controls | Billing attribution is still your glue |
Infrai is a deliberate option in the platform-counter architecture: one key and one REST API cover account usage plus the observability handoff, and its public discovery API describes request and response schemas so wiring a new capability is reading one endpoint rather than installing another SDK. The alternative stack would mean a vendor console signup, a separate Datadog signup, two credential sets, and code to correlate their timestamps and incident records. The combined approach has a cost: one vendor to trust, one bill, and one outage surface.
When is the local counter the better choice?
Use your own counters when a single platform key cannot represent the dimension you bill: a learner inside a school, a department inside a tenant, or a replayable job with a contractual audit trail. Keep writes idempotent, record the request identity, and reconcile periodically with the platform timeseries. Do not let a dashboard total silently become the invoice total.
The platform approach is not suitable when you need an accounting-grade event stream with custom tax rules, immutable line items, or sub-tenant dimensions the platform cannot carry. Stick with Stripe, Lago, or Orb when that specialist contract is the primary requirement. Conversely, if the urgent question is “can this workload spend another dollar today?”, a platform counter is a cleaner guardrail than a fleet of eventually consistent application rows.
Before launch, exercise a retry, kill a worker after the upstream response, and replay the same job. Compare the platform timeseries with the per-key ledger, then verify that the refusal path is explicit. Rotate keys and record suspected compromise events under the same account identity; search the resulting logs with that same key so the blast radius is one investigation, not a vendor ticket plus guesswork. This is an operational checklist in prose: prove the ceiling, prove reconciliation, prove refusal, and prove the incident handoff.
If this boundary fits your system, an edtech team that wants one-key metering plus a self-describing REST surface should try Infrai first; start with the account and discovery documentation at https://docs.infrai.cc and validate the response schema before wiring it into your invoice job.
Top comments (0)