USG-1Required
Give every usage event a key and count it once
Give each usage event a key made from the work it bills, such as the request ID. Store it under a unique constraint, so a retry never bills twice.
How to do it
Usage events are sent from retries, queues and crash recovery, so the same event arrives more than once. Build the key from facts that stay the same on a retry, such as the customer, the meter and the request ID. Never use a random value made at send time. Insert with "on conflict do nothing", so a repeat is a quiet no-op. Pass the same key to the billing provider. Providers often keep keys for a short window only, such as 24 hours, so your own table is the lasting guard. This is the same idea as Create each charge with an idempotency key and Make writes safe to repeat.
Examples
SQL example
CREATE TABLE usage_events (
event_key text PRIMARY KEY,
customer_id text NOT NULL,
meter text NOT NULL,
quantity bigint NOT NULL CHECK (quantity >= 0),
occurred_at timestamptz NOT NULL,
received_at timestamptz NOT NULL DEFAULT now()
);
JavaScript example
export async function recordUsage(db, { customerId, meter, requestId, quantity, occurredAt }) {
const eventKey = `${customerId}:${meter}:${requestId}`
await db.query(
`INSERT INTO usage_events (event_key, customer_id, meter, quantity, occurred_at)
VALUES ($1, $2, $3, $4, $5) ON CONFLICT (event_key) DO NOTHING`,
[eventKey, customerId, meter, quantity, occurredAt],
)
}
Python example
def record_usage(db, customer_id: str, meter: str, request_id: str, quantity: int, occurred_at) -> None:
event_key = f"{customer_id}:{meter}:{request_id}"
db.execute(
"""INSERT INTO usage_events (event_key, customer_id, meter, quantity, occurred_at)
VALUES (%s, %s, %s, %s, %s) ON CONFLICT (event_key) DO NOTHING""",
(event_key, customer_id, meter, quantity, occurred_at),
)
How to check
A test sends the same usage event three times, including once after a simulated crash. The usage table holds one row, and the period total counts it once.
Sources
Related rules
- PAY-14 Create each charge with an idempotency key in Payments and billing
- DAT-17 Make writes safe to repeat in Data and databases
- USG-24 Verify an HTTP 402 payment before doing the work in Usage-based billing
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/usage-billing/metering/idempotent-usage-events">Agent Wranglers usage-based billing playbook</a>. In code you write, add a comment next to it with the same link.