Retry and idempotency
Decision tables for safe retries and stable ids.
Safe vs unsafe retry
| Situation |
Safe retry? |
Notes |
| Fraud 401 after minting a new JWT |
Yes |
|
| Fraud 5xx / timeout on scoring |
Yes, with backoff |
May create duplicate predictions — correlate by transaction_id |
| Fraud contract validation failure |
No |
Fix body first |
| Fraud report callback 5xx on your side |
Platform may retry |
Your handler must upsert |
| KYC timeout |
Cautious |
May double vendor cost |
| KYC definitive 422 |
No |
|
Recon ingest after failure, same session_id |
Often unsafe |
Trigger guard / partial state — prefer new session |
Recon ingest, new session_id |
Yes |
Choose merge/overwrite deliberately |
Exception resolve, same resolution_request_id |
Yes |
Required on messaging path |
| Exception resolve, new id for same decision |
May double-apply |
Avoid |
Stable identifiers
| Id |
Use as |
transaction_id |
Fraud correlation / support |
x-tenant-id / tenant_id |
Partition |
session_id |
Recon run identity |
resolution_request_id |
Resolve idempotency |
provenance.predictionHash |
Report dedupe |
userId |
KYC customer key |
Deduplication boundaries
| Boundary |
Dedupe on |
| Fraud scoring HTTP |
Not guaranteed idempotent — client should not hammer identical retries without backoff |
| Fraud report delivery |
Upsert on prediction hash + transaction + tenant |
| Recon pipeline triggers |
Platform trigger guard per session/stage |
| Exception resolve |
resolution_request_id |
| Asset record events |
Record ids in consumer |
Uncertain outcomes
| Observation |
Treat as |
| Timeout with no response |
Uncertain — check status by id before assuming failure or success |
| Scoring 200, no report |
Partial — not “approved/low risk” |
| Ingest 200, status not terminal |
In flight |
| Vendor 200 no-match |
Completed negative, not transport failure |