पाठ 24 / 32
Metering Usage for Billing
यह पाठ अभी हिंदी में अनुवादित नहीं है, इसलिए अंग्रेज़ी में दिखाया जा रहा है।
Record per-tenant usage events reliably, deduplicate retries with idempotency keys, and aggregate them into billable quantities.
लेखक: Rahul Agarwal · 15 साल से वेब डेवलपर
Counting what each tenant uses
Usage-based pricing, quotas and cost analysis all need metering: recording how much of each billable unit a tenant consumes, such as API calls, active users, storage, messages or compute minutes. The usual design emits a usage event whenever something billable happens, containing the tenant, the metric, the quantity, a timestamp and a unique idempotency key. Events flow through a queue into a store where they are aggregated per tenant per billing period. Two properties matter more than anything. No double counting: networks retry, so the same event may arrive twice, and deduplicating by idempotency key prevents overbilling. No silent loss: if events are dropped you undercharge and quotas stop working, so producers should write events durably (for example via an outbox table) rather than fire-and-forget. Keep raw events long enough to answer billing disputes, and reconcile totals against independent sources such as database storage reports.
Deduplicating and aggregating events
The duplicate e1 is a retry and is counted once.
from collections import defaultdict
events = [
{"key": "e1", "tenant": "acme", "metric": "api_calls", "qty": 120},
{"key": "e2", "tenant": "zen", "metric": "api_calls", "qty": 15},
{"key": "e1", "tenant": "acme", "metric": "api_calls", "qty": 120}, # retried duplicate
{"key": "e3", "tenant": "acme", "metric": "storage_gb", "qty": 4},
]
seen = set()
usage = defaultdict(int)
for e in events:
if e["key"] in seen: # idempotency: count each event once
continue
seen.add(e["key"])
usage[(e["tenant"], e["metric"])] += e["qty"]
for (tenant, metric), qty in sorted(usage.items()):
print(tenant, metric, qty)
Output:
acme api_calls 120 acme storage_gb 4 zen api_calls 15
Bill from facts, not from logs
Application logs are sampled, rotated and reformatted, which makes them unreliable for money. Emit purpose-built usage events with a stable schema, and treat changing that schema as carefully as changing a database table.
त्वरित जाँच: A usage event for 120 API calls is delivered twice because of a network retry. What prevents the tenant being billed for 240?
- Deduplicating on the event's idempotency key
- Rounding usage down to the nearest hundred
- Billing only once per year
- Dropping all events that arrive within one second of each other
Answer
Deduplicating on the event's idempotency key — Each logical event has a unique key, so a retried delivery is recognised and ignored. Time-based dropping would lose genuine events.