A model retry is another inference attempt. Duplicate ingestion is another delivery of an event describing the same attempt. Preserve both attempt identity and event identity so deduplication does not erase real spend or inflate inference counts.
Why one request ID is insufficient
Suppose request R makes attempt A1, which times out, and then attempt A2, which succeeds. The logger delivers A2’s completion event twice after a connection failure. There are two inference attempts and three telemetry deliveries. Deduplicating on R loses the retry; counting every delivery invents another inference.
Choose the identity boundary
- Keep a user-request identifier for the complete workflow.
- Assign a new attempt identifier each time the model is actually invoked.
- Assign stable event identifiers to emitted records; reuse an event ID when retrying delivery of that record.
- Scope deduplication keys to the project or tenant as well as event identity. Document the deduplication retention window.
Check partial and late outcomes
A timeout does not necessarily mean the provider performed no work. Preserve unknown outcomes and later usage corrections rather than automatically counting them as zero cost. A repeated event with the same identity but different payload should be investigated, not silently treated as an ordinary duplicate.
What the runnable ledger demonstrates
The fixture receives three records, finds two unique events, and preserves both distinct attempts. It checks an accounting invariant; it does not implement concurrent database uniqueness or provider idempotency. Test those persistence and race boundaries separately in your ingestion service.
Run the worked example
Save the synthetic Node.js example and run node distinguish-retries-from-duplicate-ingestion.mjs with Node.js 22 or newer. The assertions check the illustrated records and calculations; they do not test a deployed provider, SDK, or access control. No credentials or network connection are needed.
// Synthetic teaching fixture. No credentials, network calls, or production verification.
import assert from 'node:assert/strict';
const deliveries = [
{ project: 'p1', request: 'r1', attempt: 'a1', event: 'e1', status: 'timeout' },
{ project: 'p1', request: 'r1', attempt: 'a2', event: 'e2', status: 'ok' },
{ project: 'p1', request: 'r1', attempt: 'a2', event: 'e2', status: 'ok' },
];
const unique = [...new Map(deliveries.map(e => [JSON.stringify([e.project, e.event]), e])).values()];
assert.equal(deliveries.length, 3);
assert.equal(unique.length, 2);
assert.equal(new Set(unique.map(e => e.attempt)).size, 2);
console.log('3 deliveries; 2 events; 2 model attempts.');
References and further reading
Maintained by DriftRail. AI assisted the October 2026 content and template revision. Examples are illustrative; they are not measured product benchmarks. Suggest a correction.