HomeServicesPortfolioAboutContactBlogCareers
Book a call
Fintech

Idempotency in a Real-Time Fraud Pipeline: Why Retries Don't Double-Score

September 2026 · ISTRALLEN Team

The same transaction, delivered twice

In a real-time fraud pipeline, a transaction event can reach your scorer more than once — the client retried after a timeout, the message queue delivers at-least-once, a consumer restarted and re-read, or someone replayed the stream for a backfill. Idempotency in fraud scoring is the property that makes a duplicate event harmless: it produces the same effect as processing it once.

Where the duplicates come from

  • At-least-once delivery. Most streaming setups guarantee a message is delivered at least once, not exactly once. A broker that doesn't get an acknowledgement in time redelivers.
  • Client retries. The service that submits a transaction for scoring times out waiting for a response and submits again — even though the first attempt may have succeeded.
  • Consumer restarts. A scorer process crashes or rebalances and resumes from the last committed offset, re-reading events it had already processed but not yet committed.
  • Deliberate replay. You reprocess a window of history to backfill a new feature or recover from a bug, and every event in that window flows through again.

What breaks without it

  • Velocity features inflate. A feature like "transactions on this card in the last 10 minutes" counts the same transaction twice. The transaction makes itself look riskier.
  • The audit trail duplicates. Two records for one decision, which a compliance reviewer then has to untangle.
  • A re-score disagrees with the first. Between the two attempts, the online feature store moved. Now you have two different scores for one transaction and no clean answer to "what did we decide."

The pattern

  • Dedupe on the transaction ID at ingestion. The authorization request already carries a unique ID — a natural idempotency key. Drop an event you've already seen.
  • Idempotent feature aggregation. Feature updates keyed by event ID, so replaying an event doesn't re-apply it.
  • A scored-transactions table keyed by ID. A repeat request returns the stored decision, it doesn't trigger a fresh scoring pass.

On our fraud-scoring project, the transaction stream is ingested once through Kafka and feeds the feature store, the scorer, and long-term retention — and every consumer treats the transaction ID as the key, so at-least-once delivery produces exactly-once effects.

Making aggregation idempotent

The velocity features are the sensitive part. Two ways to keep them correct under replay:

  • Track processed event IDs. A short-lived set of recently seen IDs (with a TTL past your longest replay window); an event whose ID is already there is skipped before it touches an aggregate.
  • Aggregate from the log, not incrementally. Compute the rolling window as a function of the retained event log rather than as a running counter you increment. Replaying the same events recomputes the same number.

The scored-transactions cache

A table keyed by transaction ID, holding the decision and its full record — score, features used, model version, routing outcome. A repeat request for the same ID reads this row and returns the stored decision. It also gives you the reconstruction the audit trail needs: one row, one decision, permanently.

The compliance angle

The audit trail must show one decision per transaction, and a retry has to be visible as a retry — not as a second, independent decision. Idempotency is what makes that record clean.

Test it deliberately

Idempotency bugs hide until a retry storm or a replay exposes them in production. In staging, submit the same transaction twice in quick succession and confirm: one audit record, one entry in the scored-transactions table, and a velocity feature that counts the transaction once. Then replay a window of events and confirm the aggregates land on the same numbers. If either check fails, you have a latent double-scoring bug waiting for a bad day.

Where this stops being right

  • Genuinely exactly-once delivery — rare in practice, and the dedupe key is cheap insurance even then.
  • Very low volume where a manual dedupe pass is acceptable.
  • Async, non-blocking scoring where a duplicate just wastes a little compute and gets cleaned up downstream.

FAQ

Isn't Kafka exactly-once? Kafka has exactly-once semantics for some configurations, but most pipelines run at-least-once in practice, and clients retry regardless. Design for duplicates.

What's the idempotency key? The transaction ID from the authorization request — it's unique and it's already there.

What if the second attempt scores differently? That's the bug idempotency prevents. Return the stored decision; don't re-score.

ISTRALLEN builds fraud pipelines where at-least-once event delivery produces exactly-once scoring and one clean audit record per transaction; see AI for Fintech.

See it in production
AI for Fintech → Fraud-scoring case study →
← All articles