# agent's idempotency keys collided across tenants: shared prefix bug

## TL;DR
Your idempotency keys were not unique per tenant, so tenant A's retry got tenant B's cached result (or vice versa). Namespace every key with the tenant id: derive keys from tenant plus request identity. A collision across tenants is a data leak, not just a retry bug.

```text
agent's idempotency keys collided across tenants: shared prefix bug
```

## Steps

1. Confirm the collision: find two requests from different tenants that shared a key and got the wrong cached result. Success check: the cross-tenant pair is documented.
2. Change key derivation to include the tenant id as a prefix or hash input. Success check: the same logical request from two tenants now produces two different keys.
3. Assess exposure: list every response served from a cross-tenant cache hit and notify affected customers per your policy. Success check: the blast radius is known, not assumed.
4. Add a uniqueness test: generate keys for identical requests across tenants and assert they differ. Success check: the test fails if anyone removes the tenant prefix.
5. Audit other shared caches (rate limit buckets, dedupe stores) for the same missing tenant scope. Success check: no other shared store keys without tenant.

## When this applies

- Idempotency keys collide across tenants in a multi-tenant system.
- One tenant receives another tenant's cached payment result.
- You are reviewing key derivation for tenant safety.

## When it doesn't

- Same-tenant key reuse with a changed payload; that is the 422 case.
- Single-tenant applications; there is no cross-tenant space to collide.
- Cache collisions in non-payment stores; same pattern, lower stakes.

## Tool + version compatibility

Any payment API with idempotency keys, in multi-tenant agent-built integrations.

### "idempotency key collision multi tenant"
Namespace keys with the tenant id; treat it as a data leak.

### "cross tenant idempotency bug"
Assess exposure first, then fix derivation.

### "idempotency key tenant prefix"
Tenant plus request identity is the minimum unique input.

## Why it happens

Idempotency keys are global to the API credential, not per tenant. If your key is just the order id or a request hash without tenant scope, two tenants with the same order id share a key, and the gateway happily returns tenant A's result to tenant B. Agent-built multi-tenant billing is where this bites: the agent generates keys from the request alone and never considers that another tenant makes the same request.

## Edge cases / pitfalls

- A cross-tenant cache hit can expose payment amounts and customer data; handle it as a privacy incident.
- Do not fix this by randomizing keys per attempt; that destroys idempotency instead of scoping it.
- Tenant id must come from authenticated context, never from client input; otherwise tenants can spoof scope.
- Rotate nothing; the keys are not compromised, the derivation is wrong. Fix the derivation.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_2HYvCGMDpUVnu7eQDa0wmw
