---
title: "Give every usage event a key and count it · Agent Wranglers"
url: https://agentwranglers.se/playbook/usage-billing/metering/idempotent-usage-events
id: USG-1
level: Required
applies: payments
risk: money
updated: 2026-10-22
tokens: 1086
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Give every usage event a key and count it once

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Metering](https://agentwranglers.se/playbook/usage-billing/metering.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-22.

- ID: USG-1
- Level: Required
- Chapter: [Metering](https://agentwranglers.se/playbook/usage-billing/metering.md)
- Rule: 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.
- 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.
- Risk: Money lost or taken twice
- Applies when: The project takes payments.
- How: 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](https://agentwranglers.se/playbook/payments/amounts-and-orders/idempotent-charge-creation.md) and [Make writes safe to repeat](https://agentwranglers.se/playbook/data/transactions-and-concurrency/idempotent-writes.md).

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### SQL example

```sql
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

```js
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

```python
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),
    )
```

## Sources

- [Stripe recording usage, idempotency and identifiers](https://docs.stripe.com/billing/subscriptions/usage-based/recording-usage-api)
- [Stripe idempotent requests](https://docs.stripe.com/api/idempotent_requests)

## Related rules

- PAY-14 [Create each charge with an idempotency key](https://agentwranglers.se/playbook/payments/amounts-and-orders/idempotent-charge-creation.md) in Payments and billing
- DAT-17 [Make writes safe to repeat](https://agentwranglers.se/playbook/data/transactions-and-concurrency/idempotent-writes.md) in Data and databases
- USG-24 [Verify an HTTP 402 payment before doing the work](https://agentwranglers.se/playbook/usage-billing/agentic-payments/http-402-payments.md) in Usage-based billing

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/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.

- Next: [Meter on the server after the work succeeds](https://agentwranglers.se/playbook/usage-billing/metering/server-side-metering.md)
- [Metering](https://agentwranglers.se/playbook/usage-billing/metering.md)
