Duplicate billing events are a structural feature of distributed systems, not an edge case. Retry logic, network instability, application restarts, and message queue redelivery guarantees all produce situations where the same billable event gets submitted to your billing system more than once. If your billing platform doesn’t deduplicate correctly, those duplicates generate overcharges and customers find them before you do.
The goal of event deduplication in billing is to rate every unique billable event exactly once. Not twice (overcharge), not zero times (revenue loss), not once for most events and occasionally twice for others (systematic but intermittent overcharges, which are the hardest to detect). Exactly once. Every time. At any volume.
Most companies discover they have a deduplication problem in the worst possible way: a customer notices their bill is materially higher than expected and opens a dispute. The overcharges have usually been accumulating for weeks or months, because a 0.1% duplication rate doesn’t generate a complaint for every duplicate event. You get one complaint when the cumulative effect finally becomes visible in an invoice. Finding and correcting systematic duplicate billing retroactively, with live invoices already issued, is orders of magnitude harder than preventing it. The earliest signal is almost always in your raw event logs, not your invoice reports. Most teams don’t look there until after the dispute.
Where Duplicates Come From
Retry Logic
The most common source. When an event producer submits a usage event to your billing system and doesn’t receive an acknowledgment within a timeout window, it retries. If the first request actually succeeded but the response was delayed or lost, you now have two copies of the same event in the pipeline. At low transaction volumes, this is an occasional nuisance. At 10 million events per day, a 0.5% retry rate is 50,000 potential duplicates daily.
At-Least-Once Delivery Guarantees
Most message queues and streaming platforms (Kafka, SQS, Pub/Sub) operate under at-least-once delivery semantics by default. They guarantee that every message is delivered, but not that it’s delivered exactly once. This is a conscious design choice: exactly-once delivery is significantly more complex and expensive to achieve at the infrastructure level. The practical implication is that your application receives duplicate messages, and you are responsible for handling them correctly.
If your event ingestion pipeline sits downstream of any of these systems, you’re receiving duplicates. The question is whether your billing system handles them.
Application Restarts and Failure Recovery
When a service that produces billing events restarts after a failure, it may replay recent events as part of its recovery process. If it doesn’t maintain a record of which events it has already successfully submitted, it will re-submit them. This is especially common in IoT and telemetry pipelines, where device firmware implements simple “send everything in the buffer on reconnect” recovery logic without any deduplication awareness.
Integration Layer Bugs
Homegrown integration layers between your product and your billing system are fertile ground for duplicate event generation. A bug in a webhook handler, a cron job that fires twice under certain conditions, a synchronization issue between two data sources that each track the same usage metric. Any of these can produce systematic duplicate streams that persist until someone notices the invoice anomalies.
How Event Deduplication in Billing Works: The Idempotency Key Pattern
The standard approach to event deduplication in billing is the idempotency key pattern. Every usage event carries a unique identifier (the idempotency key) that is generated by the event producer and remains stable across retries. The idempotency key for a given event is the same whether the event is submitted once, twice or ten times.
The billing system maintains a log of processed idempotency keys. When an event arrives, the system checks the key against this log. If the key has been seen before, the event is a duplicate and is discarded. If the key is new, the event is processed and the key is added to the log.
This approach works reliably as long as three conditions are met:
- Every event has a stable, unique idempotency key. The billing system can’t generate it; a key created at receipt is a new key every time, which means retries aren’t caught. The producer has to generate it before the first submission and keep it stable across retries.
- The key is derived from event content, not from submission metadata. Anything the receiving system generates (a server timestamp, a sequential ID) will differ between the original submission and the retry. Base it on attributes of the event itself: customer ID, the event’s own timestamp, metric type, quantity.
- The idempotency log is durable and long-lived. An in-memory log doesn’t survive a restart. Anything submitted before the restart becomes a potential duplicate the next time it arrives. The log needs to be on durable storage, and the lookback window should cover at least several days, longer for pipelines where events can arrive significantly late.
The Over-Deduplication Problem
Getting event deduplication in billing wrong in the over-aggressive direction is less common (but equally damaging). If your deduplication logic discards events that aren’t actually duplicates (because they share some characteristics with a previous event but are genuinely distinct), you’re dropping real usage and under-billing.
This happens most often when teams implement heuristic deduplication instead of key-based deduplication. For example: “if we receive two events with the same customer ID, metric type and quantity within five minutes of each other, treat the second as a duplicate.” The problem: a customer who does the same thing twice in five minutes (two API calls of the same size, two identical data uploads) has their second event silently dropped.
Idempotency key-based deduplication avoids this entirely. The key is stable and unique. If two different events happen to share the same customer ID, metric type and quantity but have different keys, they’re different events and both are processed. The key is the only arbiter.
Scale Considerations
The idempotency log approach is conceptually simple but creates real engineering constraints at scale. At 10 million events per day, the log accumulates 300 million entries per month. Key lookup time, log storage and log retention policies all become non-trivial design decisions.
For a billing platform this is a solved problem, but it’s solved in different ways by different vendors, with different performance characteristics and different retention windows. Ask specifically:
- What is the retention window for the idempotency log? If a retry arrives 30 days after the original event, is it correctly identified as a duplicate?
- What is the lookup time for a key check at peak event volume? Does deduplication add latency to the ingestion pipeline?
- Is the idempotency log durable through system restarts and infrastructure failures?
Detecting Duplicate Events You’re Already Generating
If you’re not sure whether your system is generating duplicates, here’s a practical check:
Pull a sample of billing events from a single day. For each event, check whether the same customer ID, metric type, quantity and approximate timestamp appear more than once in the log. A non-trivial duplication rate (even 0.1%) is a signal that your event producers are generating retries that aren’t being caught.
If your billing system doesn’t expose raw event logs. If all you can see is the aggregated metered quantity, you can’t perform this check. That itself is a signal. You should be able to inspect the raw event stream that fed any invoice.
Frequently Asked Questions
What is event deduplication in billing?
Event deduplication is the process of identifying and discarding usage events that have already been processed, so that duplicate submissions don’t result in overbilling. Because most event delivery systems use at-least-once semantics (guaranteeing delivery but not exactly-once delivery), billing systems receive duplicate events as a matter of course. Deduplication is the mechanism that converts at-least-once delivery into exactly-once billing.
What causes duplicate billing events?
Three main causes: at-least-once delivery guarantees from message queues like Kafka or SQS, which may deliver each message more than once; application restarts and failure recovery, where services replay buffered events on reconnect without checking whether they were already delivered; and integration layer bugs in custom connectors, particularly webhook handlers or scheduled jobs that can fire more than once under certain conditions.
What is an idempotency key in event processing?
An idempotency key is a unique, stable identifier attached to each usage event by the event producer. The key must be generated before the first submission attempt and remain unchanged across retries. The billing system maintains a log of all keys it has seen; when an event arrives, the key is checked — if it’s been seen before, the event is discarded. The key must come from the producer, not the receiving system: a key generated at receipt is always a new key, which means retries are never recognized as duplicates.
What is over-deduplication and why is it dangerous?
Over-deduplication happens when your deduplication logic discards events that aren’t actually duplicates because they share characteristics with a previous event but represent genuinely distinct usage. For example, if your logic drops any second event with the same customer ID, metric type and quantity within five minutes, you silently discard a customer’s second identical API call. Over-deduplication causes underbilling and generates no customer complaints, so it can persist indefinitely. Idempotency key-based deduplication avoids this entirely: the key is the only arbiter, not the content.
How do you test whether your billing system is generating duplicate charges?
Pull a sample of billing events from a representative day. For each event, check whether the same customer ID, metric type, quantity and approximate timestamp appear more than once in the log. A duplication rate above 0.1% signals that event producers are generating unhandled retries. If your billing system doesn’t expose the raw event stream — only aggregated quantities — you can’t perform this check. That limitation itself is a signal: a billing system that can’t show you its raw event log makes it impossible to diagnose the source of any billing discrepancy.
For the complete practitioner guide to metering and rating, see billingplatform.com/metering-and-rating.
See also: What Causes Revenue Leakage — and How to Stop It | What Is Billing Mediation? | How Rating Engines Work: A Technical Guide | Formula-Based Pricing: When Tier Lookups Aren’t Enough | How to Evaluate a Metering & Rating Platform