What Is Webhook Replay Protection and Why Does It Matter?

Webhook replay protection is the set of controls that stops an attacker from capturing a valid webhook request and sending the same request again later to trigger an unwanted action. A valid HMAC signature does not by itself prevent replay: if an attacker copies the entire request, including its body, timestamp, and signature, the copy may verify exactly as the original did. The receiving system must therefore treat a request as fresh only during a limited acceptance window and must remember recently processed event identifiers. For B2B support, compliance, and public-affairs teams, this matters because a repeated event can create duplicate cases, reopen resolved investigations, send duplicate notifications, or alter an approval or escalation record. The technical controls are straightforward, but their operational settings need to match the sender’s retry policy. As of 25 September 2026, the safest default is a five-minute signature window combined with persistent event-ID deduplication, rather than relying on either control alone. HMAC-SHA256 remains a sound choice for authenticity, while idempotency records supply the missing property of one-time processing.

Also worth reading: What Are Agentic Identity Security Patterns and How Do They Protect Enterprise AI Systems in 2026? · How Do You Design Reliable Webhook Replay for Case and Compliance Workflows? · How Does Case Workflow Automation Work for Support, Compliance, and Public-Affairs Teams in 2026?

A replay is not necessarily a broken password attack or a forged signature. It is often a valid message observed at an incorrect point in the delivery chain, then reused. That can happen through a compromised intermediary, an exposed request logger, a proxy that retains bodies, or a sender whose retry queue contains stale deliveries. Webhook sender Stripe has historically recommended a five-minute tolerance when validating signatures, which is a useful reference point for many event systems. That tolerance is not a universal expiry contract, however. Systems processing payments or changing case status should usually store processed event IDs for longer than the sender’s longest retry period, often 24 hours to seven days, depending on business requirements. The key distinction is between rejecting an old signature and ignoring a duplicate business event; the first is time-based, and the second requires state.

How Webhook Replay Attacks Work in Practice

An attacker usually begins by obtaining a legitimate request rather than inventing one. The request may be visible in an application log, browser developer tool, proxy, support attachment, container environment, or compromised employee account. The attacker can preserve the raw body and headers and resend them to the original endpoint. If the receiver checks only the HMAC value, the replayed request may pass authentication. The danger appears when the handler performs a non-idempotent action, such as inserting a second ticket, issuing another refund, sending a second alert, or moving a workflow to a completed state. The attacker does not need to break SHA-256; they need a message that was already signed.

The attack becomes more practical when an application accepts webhook requests over an unprotected path, stores complete payloads in a shared log, or allows internal services to call the public endpoint without separate controls. A captured request can also be replayed from a different IP address, so IP allowlists are not a complete answer. Providers such as Stripe include a webhook ID in their event envelope, and other platforms use similar identifiers, but teams should not assume that every field name is identical. The receiver should extract the provider’s official event ID and persist it atomically with the business operation. If two identical requests arrive at nearly the same time, a simple “check, then insert” sequence can still race unless the database enforces uniqueness. A replay test should therefore include parallel deliveries, not just one request sent after a delay.

Replay protection differs from replay debugging. A debugger or request-capture service may deliberately resend a request to help an operator reproduce an integration issue, and an OS-level alternative to RequestBin may include replay functionality. Those tools are useful for development, but they increase the need for isolated environments, redacted credentials, and short-lived test endpoints. A debugging tool should never be treated as proof that a production endpoint is safe. The same capture-and-resend capability that helps a support team reproduce a complaint can give an unauthorized user a ready-made replay if logs or proxies are exposed.

HMAC Signatures, Timestamps, and Event IDs Do Different Jobs

HMAC-SHA256 verifies that the sender possesses a shared secret and that the body has not changed during transit. Verification normally involves recomputing an HMAC over the exact bytes received, using the provider’s documented signing format, and comparing it with the supplied signature using a constant-time function. This prevents an attacker who does not know the secret from modifying the body or generating a new valid signature. It does not prove that the request is new. Reusing a valid body and signature preserves the MAC, so signature verification alone can accept a replay indefinitely unless the protocol includes freshness information.

A timestamp or provider-generated delivery time creates a bounded acceptance window. The receiver compares the timestamp in the request with its own clock and rejects requests outside the permitted window. This blocks old captures from being accepted, but it can create false failures when clocks drift, network queues are delayed, or a sender retries for several hours. A five-minute window is a common starting point for signature freshness, not a guarantee that every legitimate delivery will arrive within five minutes. Teams with long processing queues should separate transport authentication from event processing, then handle delayed events through an explicit retry or dead-letter workflow rather than silently widening the window.

Event IDs solve a different problem: they identify the same business event across retries. A sender may deliver the same event again after a timeout, even when the original request was received successfully but the acknowledgment was lost. The receiver should accept the first event, record its provider event ID, and return success for later duplicates without repeating the business action. A durable uniqueness constraint on the event ID is stronger than an in-memory cache because process restarts must not erase the replay record. A practical design uses HMAC for authenticity, a short timestamp window for freshness, and a longer-lived event-ID ledger for idempotency.

ControlWhat it provesWhat it does not proveRecommended use
HMAC-SHA256 verificationThe body matches a message signed with the shared secretThat the message has not been sent beforeAuthenticate every request before parsing business fields
Timestamp windowThe signed request is recent enough for the protocolThat the same event was not retried within the windowStart around 5 minutes; tune to delivery conditions
Event-ID uniquenessThis provider event has already been processed or reservedThat the payload is authenticEnforce with a durable database constraint
Atomic transactionThe deduplication record and business action succeed togetherThat an external side effect happened only onceUse transactional outbox or provider idempotency where needed
IP or network restrictionThe request came from an expected network pathThat an authorized network actor cannot replay itAdd as defense in depth, not the primary control
## A Practical Implementation for Case and Workflow Systems

The endpoint should first preserve the raw request body before any JSON parsing or normalization. JSON libraries can reorder keys, change whitespace, or convert numbers, producing bytes that no longer match the sender’s signature. The handler should reject oversized bodies early, such as above 1 MB unless the provider’s documented payload size requires more, and it should apply a request rate limit without treating rate limiting as replay protection. Next, verify the provider signature against the exact raw bytes, using the secret stored in a secret manager rather than in source code or a general environment variable visible to every service. Verification failures should produce a generic response and a structured internal log event; the response should not reveal whether the endpoint exists or which part of the signature failed.

After authentication, parse the payload and extract the provider event ID. Check a durable store for that ID, but make the check and reservation atomic. In a relational database, insert the ID with a unique constraint before performing the case update, or perform both operations in one transaction. If the insert conflicts, return the provider’s expected success response without executing the action again. Do not delete the event record after a short cache TTL if retries can arrive later. For a support case platform, retain IDs for at least the longest documented retry period, plus a safety margin; seven days is a reasonable starting point for many systems, while regulated or financial workflows may need longer. Exact retention should follow contractual, audit, and data-minimization requirements rather than an arbitrary number.

The business operation itself should be idempotent wherever possible. Creating a case should use the provider event ID or an internal operation key as its uniqueness boundary, not merely a check that the external reference number is absent. Sending a notification should record its dispatch state, and a retry should either reuse the same idempotency key or suppress the duplicate. Webhook infrastructure such as Hookaido is positioned as a “Caddy for Webhooks,” while webhook debugging tools emphasize replay, SSRF checks, and HMAC-SHA256 examples. These tools can help teams route and inspect traffic, but the application still owns event identity and business idempotency. A proxy cannot know whether two authenticated events should produce two legitimate case updates or one duplicated action without information from the application contract.

Choosing Storage: Database, Queue, Cache, and Managed Services

The deduplication store must survive process restarts and, ideally, a complete deployment replacement. A database table is usually the clearest choice for teams already operating B2B case management or compliance software. It supports unique constraints, transactions, audit queries, and retention policies. The cost is a write for every accepted event and the need to manage growth; a table containing only provider ID, received time, status, and a small hash can be lighter than storing full webhook payloads. Teams should avoid storing sensitive full payloads indefinitely unless the business purpose requires them. Encryption at rest, access controls, and deletion schedules still apply to webhook records because payloads may contain personal or case information.

A queue-based design can make processing more resilient, but the deduplication decision must happen before an event is handed to multiple workers. A durable queue alone does not guarantee exactly-once business processing. It may provide at-least-once delivery, so the consumer still needs a unique event record and an idempotent handler. Redis or another in-memory cache is useful for short-lived rate limits and rapid duplicate suppression, but cache eviction, memory pressure, or a restart can reopen the replay window. A cache can complement a database, not replace it, unless the team can explicitly accept a bounded loss of state. A managed webhook relay may reduce operational work, but teams should verify whether it stores event IDs, supports signature validation, exposes replay settings, and prevents duplicate forwarding. “Exactly once” marketing language should be tested against a forced worker crash and a repeated delivery.

Storage or relay optionStrengthMain limitationTypical fit
Relational databaseTransactions, unique IDs, auditabilityApplication-managed writes and retentionCase, compliance, and approval systems
Durable message queueRetries and back-pressureStill needs consumer idempotencyHigh-volume or asynchronously processed events
Redis cacheVery fast duplicate checksVolatile unless persistence is designed inShort-window throttling, not sole evidence
Managed webhook relayLess routing and monitoring workVendor lock-in and configuration limitsTeams prioritizing operations over control
In-process mapMinimal setupLost on restart and unsafe across replicasLocal development only
The operating model should include metrics such as accepted events, signature failures, stale timestamps, duplicate IDs, processing latency, dead-letter volume, and storage growth. Duplicate rate should be interpreted carefully: a healthy sender retrying after a timeout may generate duplicates, while an attack can also produce them. The useful signal is the ratio of duplicates to accepted events and whether each duplicate was correctly suppressed. A system that accepts the first event but still sends a second notification has not solved replay protection even if the HTTP response was correct.

Time Windows, Retries, Clocks, and Delivery Semantics

A common implementation mistake is setting the timestamp tolerance to zero. Network latency and clock drift make that impractical, and it creates avoidable outages. Another mistake is setting it to 24 hours because a provider sometimes retries for a long time, which gives a captured request a large replay opportunity. Teams should distinguish signature freshness from retry tolerance. A provider may legally resend an old event after a failed acknowledgment, but the receiver can process that event through a trusted replay path if it has the original event record. If the event is unknown and its timestamp is far outside the signature window, reject it. If the timestamp is acceptable but the event ID is already known, acknowledge it without repeating work. This separation allows a short security window without breaking normal retries.

Clock synchronization matters. Use network time synchronization on both sender and receiver infrastructure, and alert if drift approaches the freshness threshold. The exact tolerance should reflect the provider’s documented behavior, the organization’s latency profile, and the cost of false negatives. A five-minute window is a defensible default for many integrations, but an organization with scheduled public-affairs alerts may prefer 10 minutes during a known outage, while a high-risk payment workflow may keep 2–5 minutes and compensate with event-ID state. These are engineering choices, not universal standards. The documentation should state the chosen window, why it was chosen, and how operators handle a delayed event.

Retries also interact with response codes. Return a success status only after the event has been durably accepted or safely suppressed. A timeout before commit should lead to a retry, and the retry must encounter the uniqueness constraint. Return a temporary error only when the event can be retried safely; do not report success merely because the request was parsed. Dead-letter records should retain enough metadata to diagnose the failure, while secrets and unnecessary personal data should be redacted. For teams sending crypto or market notifications, real-time update guides such as CoinGecko’s webhook material emphasize avoiding polling, but low latency does not justify weak verification. An update delivered in 200 ms can still be a replay, and a legitimate delay should not force the system to accept an unlimited old request.

Common Mistakes and the Tests That Expose Them

The first common mistake is verifying a JSON-reserialized payload rather than the exact received bytes. This produces intermittent signature failures that developers may “fix” by disabling verification, which removes protection entirely. The second is storing only a hash of the payload and assuming that identical bytes always mean a duplicate. Two distinct legitimate events can have similar fields, while the same provider event can be delivered with transport differences. Prefer the provider’s event ID and use a payload hash only as a secondary diagnostic. The third is checking an event ID in application memory or a cache without a durable write barrier. Deployments, autoscaling, and regional failover make that design unreliable.

Another mistake is trusting a proxy’s source address as proof of authenticity. An attacker inside a trusted network, a misconfigured proxy, or a request forwarded by an internal service can still replay a valid capture. Network restrictions are useful for reducing exposure, but they should complement HMAC verification and durable deduplication. Teams also make the mistake of logging complete signed requests. Logs are often copied into support tools, monitoring systems, and developer workstations, expanding the number of places where a replayable message exists. Redact authorization headers, signing secrets, and unnecessary personal fields. A webhook debugger should be isolated, access-controlled, and used against test data where possible.

Replay tests should cover a valid first request, an identical request after one minute, a duplicate after 24 hours, a request with a future timestamp beyond the allowed clock skew, a request with a modified body, a request with an invalid signature, and two concurrent copies of the same event ID. The expected result is not the same in every case: a recent duplicate should normally receive success without a second business action, while an old unknown event should be rejected or quarantined. Test process termination after authentication and before the database commit. Test a lost acknowledgment followed by a sender retry. These cases reveal whether protection belongs in the real transaction path rather than only in a middleware abstraction.

When to Act and What It May Cost

Teams should implement replay protection before exposing a production webhook endpoint, not after the first suspicious duplicate. The minimum viable control set is raw-body signature verification, a bounded timestamp window, a durable provider event-ID record, an atomic uniqueness check, and an idempotent business handler. Add rate limiting, SSRF-safe outbound behavior, secret rotation, alerting, and audit trails as the integration becomes more sensitive. Organizations handling compliance evidence or public-affairs escalations should document who can view raw payloads and how long they remain available. A case created by a replayed event can affect deadlines, notifications, and reporting, so the audit record should distinguish the original event from subsequent duplicate attempts.

The cost depends heavily on volume and architecture. A small internal integration may use an existing database and cost only the storage and operational overhead of a few additional writes per event. At 100,000 events per day, one lightweight deduplication record per event can become a meaningful data-management decision, especially if retained for 30 days: that is roughly 3 million records before indexing and metadata. Managed webhook relays may reduce engineering time but can introduce per-event, per-endpoint, or subscription pricing; obtain current vendor quotes rather than relying on an old benchmark. Self-hosted proxy and queue infrastructure can be inexpensive at low volume but requires monitoring, patching, capacity planning, and on-call ownership. The relevant cost is not only the subscription fee; it is the engineering and incident cost of duplicate actions, missed deadlines, and forensic reconstruction.

There is little reason to buy a dedicated product merely to store a five-minute cache, but a durable relay becomes more attractive when several teams need routing, retries, filtering, and centralized monitoring. Evaluate alternatives against the actual threat model and the provider’s protocol. Ask whether the system validates signatures itself, records event IDs before processing, survives restarts, supports retention controls, and exposes duplicate counts. A cryptographic HMAC implementation is not expensive in itself, although HMAC versus SHA-256 discussions sometimes frame CPU costs as a security tradeoff; the correct comparison is the documented HMAC construction with constant-time comparison, not a choice between secure HMAC and plain SHA-256. For most B2B issue-ops systems, a database-backed ledger is the practical starting point, with a queue or managed relay added when delivery complexity justifies it. The decisive standard is whether every accepted event can be traced, every duplicate is harmless, and every old or altered request fails for a documented reason.