Hookbase
LoginGet Started Free
Back to Blog
Product Update

Webhook Deduplication: Never Process the Same Event Twice

Automatically prevent duplicate webhook processing with intelligent deduplication strategies. Works out-of-the-box with Stripe, GitHub, Shopify, and 10+ providers.

Hookbase Team
January 25, 2026
8 min read

The Problem with Webhook Retries

If you've worked with webhooks, you've likely encountered this scenario: a network hiccup causes a provider to retry a webhook, and suddenly your system processes the same order twice, sends duplicate notifications, or creates duplicate records.

Webhook providers are designed to be reliable. When they don't receive a successful response, they retry. Stripe, for example, retries webhooks every 5 minutes for up to 3 days. This reliability is a feature, not a bug:but it creates a challenge for your backend.

Without deduplication, each retry looks like a new event:

  • Duplicate charges processed for the same order
  • Multiple notification emails sent for a single event
  • Inventory counted twice for one purchase
  • Analytics skewed by phantom events

The traditional solution? Write custom deduplication logic for every webhook source. Store event IDs, manage expiration, handle race conditions. It's tedious, error-prone, and different for every provider.

The Solution: Automatic Deduplication

Hookbase now handles all of this automatically. When you enable deduplication on a source, every incoming webhook is checked against recent events before processing. Duplicates are detected in sub-millisecond time and flagged:no deliveries are triggered, but a full audit trail is maintained.

Five Deduplication Strategies

Different use cases call for different approaches. Hookbase supports five strategies:

1. Auto (Default)

The smart choice for most setups. Auto mode uses the provider's event ID when available, falling back to a payload hash when it isn't.

{
  "dedupStrategy": "auto",
  "dedupWindowHours": 24
}

2. Provider ID

For providers with guaranteed unique event identifiers. Hookbase extracts these automatically:

| Provider | ID Source | |----------|-----------| | Stripe | id field (evt_xxx) | | GitHub | X-GitHub-Delivery header | | GitLab | X-GitLab-Delivery header | | Shopify | X-Shopify-Webhook-ID header | | Slack | envelope_id field | | Twilio | X-Twilio-Message-SID header | | SendGrid | X-Message-ID header | | Paddle | event_id field | | Linear | Linear-Delivery header | | Vercel | X-Vercel-ID header | | Discord | id field |

3. Payload Hash

Creates a SHA-256 hash of the entire webhook payload. Two identical payloads within the time window are considered duplicates.

Best for generic webhooks without unique identifiers.

4. Idempotency Key

Uses a custom header for deduplication. Clients can include an idempotency key to ensure exactly-once processing.

{
  "dedupStrategy": "idempotency_key",
  "dedupCustomHeader": "x-idempotency-key"
}

5. None

Disables deduplication entirely. Useful for testing or when you genuinely want to process every webhook.

Configurable Time Windows

The deduplication window determines how long Hookbase remembers event IDs. Configure anywhere from 1 hour to 7 days:

{
  "dedupEnabled": true,
  "dedupStrategy": "auto",
  "dedupWindowHours": 48
}

The default is 24 hours:long enough to catch most retry patterns.

How It Works Under the Hood

When a webhook arrives at Hookbase:

  1. Key Generation: Based on your strategy, we generate a deduplication key
  2. Cache Lookup: We check Cloudflare KV for the key (sub-millisecond)
  3. Duplicate Handling: If found, the event is stored with is_duplicate: true and linked to the original. No deliveries are created.
  4. New Event Processing: If not found, we record the key and process normally

Response for Duplicates

When a duplicate is detected, Hookbase returns a 202 response with details:

{
  "success": true,
  "eventId": "evt_new_abc123",
  "originalEventId": "evt_original_xyz789",
  "duplicate": true,
  "message": "Duplicate event detected and stored"
}

Your downstream systems can use originalEventId to trace back to the first occurrence.

Configuration via API

Enable Deduplication on a New Source

curl -X POST https://api.hookbase.app/api/organizations/{orgId}/sources \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Stripe Production",
    "slug": "stripe-prod",
    "provider": "stripe",
    "dedupEnabled": true,
    "dedupStrategy": "auto",
    "dedupWindowHours": 24
  }'

Update an Existing Source

curl -X PATCH https://api.hookbase.app/api/organizations/{orgId}/sources/{sourceId} \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "dedupEnabled": true,
    "dedupStrategy": "provider_id",
    "dedupWindowHours": 48
  }'

Benefits at a Glance

  • Zero custom code : Enable with a single API call or UI toggle
  • Sub-millisecond performance : Powered by Cloudflare's edge KV storage
  • Full audit trail : Duplicates are stored and linked to originals
  • 10+ providers supported : Native ID extraction for major webhook senders
  • Flexible strategies : From automatic to manual control
  • Cost savings : Don't waste compute on duplicate processing

Getting Started

  1. Navigate to Sources in your Hookbase dashboard
  2. Edit your source or create a new one
  3. Enable Deduplication and select your strategy
  4. Set the time window (1-168 hours)
  5. Save : duplicates are now automatically detected

Already using Hookbase? Deduplication is available now on all plans. New to Hookbase? Sign up free and start receiving webhooks with built-in reliability.

product-updatededuplicationreliabilitywebhooks

Related Articles

Product Update

Test Real Webhooks in CI With Three Lines of YAML

The new hookbase/setup-tunnel GitHub Action exposes a localhost port via a public Hookbase tunnel during CI runs. Receive real webhooks from Stripe, GitHub, Shopify, or any provider against ephemeral test environments — without managing tunnel lifecycle by hand.

Tutorial

Shopify Webhook Signature Verification, Explained

Shopify HMAC verification trips up almost every first-time integrator. Here is exactly how the signature is computed, what goes wrong, and a working implementation in Node, Python, Go, and Ruby.

Reference

Webhook Retries: What Every Provider Does Differently

Stripe retries for 3 days. GitHub gives up after one failure. Shopify retries 19 times. Knowing the rules for each provider is the difference between losing events and not. A reference table plus what it means for your handler.

Ready to Try Hookbase?

Start receiving, transforming, and routing webhooks in minutes.

Get Started Free
Hookbase

Reliable webhook infrastructure for modern teams. Built on Cloudflare's global edge network.

Product

  • Features
  • Pricing
  • Use Cases
  • Integrations
  • ngrok Alternative

Resources

  • Documentation
  • API Reference
  • CLI Guide
  • Blog
  • FAQ

Free Tools

  • All Tools
  • Webhook Bin
  • HMAC Calculator
  • JSONata Playground
  • Cron Builder
  • Payload Formatter
  • Local Testing

Legal

  • Privacy Policy
  • Terms of Service
  • Contact
  • Status

© 2026 Hookbase. All rights reserved.