Back to Blog
backend
webhooks
redis
architecture
scalability

High Volume Webhook Processing Architecture

October 8, 2026

Design scalable backend architecture to process high volume webhooks using Redis queue buffering, idempotent workers, and rate limiting.

High Volume Webhook Processing Architecture Guide

High volume webhook processing requires a decoupled, asynchronous queue architecture that immediately acknowledges incoming HTTP POST payloads with a 202 Accepted status in under 50 milliseconds while pushing event jobs into a distributed message broker like Redis or Amazon SQS. Processing webhooks synchronously on incoming webservers causes connection pool exhaustion, memory spikes, and dropped payloads when traffic surges to 100k events per minute. Decoupling ingestion from execution guarantees zero message loss, rate limits downstream database writes, and handles provider retries idempotently.


Core Architecture for High Volume Webhook Ingestion

Building a system capable of handling high volume webhook processing demands a clear separation of concerns between receiving data and processing data. When third-party platforms such as Stripe, Shopify, GitHub, or custom IoT sensors transmit thousands of HTTP POST events per second, treating the receiving HTTP server as an execution engine creates immediate bottlenecks.

+-------------------------------------------------------------------+
|                        Webhook Producers                          |
|             (Stripe, Shopify, GitHub, IoT Sensors)                |
+---------------------------------+---------------------------------+
                                  | HTTP POST
                                  v
+-------------------------------------------------------------------+
|               API Gateway Ingestion Layer (Fastify / Go)           |
|  1. Verify HMAC Signature                                         |
|  2. Push to Queue & Return HTTP 202 Accepted (<30ms)               |
+---------------------------------+---------------------------------+
                                  |
                                  v
+-------------------------------------------------------------------+
|              Buffered Message Queue (Redis / BullMQ / SQS)         |
+---------------------------------+---------------------------------+
                                  |
        +-------------------------+-------------------------+
        |                                                   |
        v                                                   v
+-------------------------------+   +-------------------------------+
|  Worker Node Pool (Consumer)  |   |  Worker Node Pool (Consumer)  |
+---------------+---------------+   +---------------+---------------+
                |                                   |
                +-----------------+-----------------+
                                  |
                                  v
+-------------------------------------------------------------------+
|                 Target Database (PostgreSQL Upsert)               |
+-------------------------------------------------------------------+

Why Synchronous Webhook Handlers Fail at Scale

In a traditional synchronous handler, the receiving endpoint performs multiple sequential tasks before returning an HTTP response: parsing the JSON body, validating signatures, querying the database, executing business logic, and updating row states.

Under normal conditions with low traffic, this process takes 150 to 400 milliseconds. However, when an upstream platform sends bursts of 100k events per minute, three catastrophic failures occur:

  • Thread Pool Exhaustion: Node.js event loops freeze under CPU-bound signature parsing, or web workers exhaust their worker pool, rejecting connections with 502 Bad Gateway or 504 Gateway Timeout.
  • Database Connection Pool Collapse: Concurrent HTTP requests open database connections. PostgreSQL connection limits are hit, causing connection refused errors across the stack.
  • Provider Disablement: Major webhook providers automatically suspend delivery if the endpoint fails to return a 2xx response within 5 seconds.

To eliminate these vulnerabilities, deploy a lightweight API Gateway built with runtimes such as Fastify (Node.js) or Go that executes only signature verification and queue enqueuing before terminating the connection.

For microservices engineering and API infrastructure, review our backend and API development services.


Message Queue Buffering Layer: Redis & Amazon SQS

The message queue serves as a buffer between external webhook senders and internal database infrastructure. Regardless of whether incoming volume spikes to 100k events per minute, the ingestion gateway enqueues messages at constant speed, allowing downstream workers to process events at a controlled rate.

Queue Technology Selection

| Feature / Criteria | Redis (BullMQ) | Amazon SQS | Apache Kafka | | --- | --- | --- | --- | | Ingestion Latency | Sub-millisecond (< 2ms) | 10ms – 25ms | Sub-millisecond (< 5ms) | | Throughput Target | Up to 100,000 events/sec | Virtually unlimited | Exceeds 1,000,000 events/sec | | Ordering Guarantees | Strict FIFO per queue | FIFO mode available | Strict per partition key | | Operational Effort | Low to Medium | Zero (Serverless) | High (Requires Cluster Tuning) |

For high volume webhook processing implementations handling up to 100k events per minute, Redis paired with BullMQ offers low latency ingestion, minimal overhead, and rich queue primitives.

Dead Letter Queues (DLQ) and Retention

Events that fail execution due to schema mismatches or database outages must not block the queue. Configure a Dead Letter Queue policy:

  • Max Retry Count: 5 attempts with exponential backoff (e.g., 2s, 8s, 32s, 128s, 512s).
  • DLQ Routing: Move failed jobs after max retries to a dedicated webhook-dlq queue.
  • TTL Retention: Retain raw payloads in the DLQ for 14 days to enable inspection and re-play.

Worker Execution Pool & Idempotency Key Handling

Webhook providers deliver events with an "at-least-once" guarantee. Due to transient retries or timeouts, your backend receives duplicate events. Without idempotency protections, processing duplicate webhooks leads to duplicate charges and corrupted state.

Atomic Idempotency Pattern Using Redis

To enforce idempotency without querying primary databases on every event, workers execute an atomic lock check in Redis using SETNX:

  1. Extract Event ID: Identify the unique identifier generated by the provider (e.g., Stripe evt_...).
  2. Atomic Lock Acquisition: Execute SET webhook:idempotency:{event_id} processing NX EX 86400 (setting a 24-hour expiration window).
  3. Branch Logic:
    • If Redis returns NULL (key exists), terminate processing immediately.
    • If Redis returns OK (key created), proceed with downstream payload parsing.
  4. Completion State: Upon successful database persistence, update the Redis key value to completed.

Database Write Batching and Downstream Rate Limiting

Inserting row by row into PostgreSQL during a 100k events per minute surge generates write amplification and disk I/O bottlenecks. Workers aggregate individual events into memory buffers and execute multi-row bulk updates.

Bulk PostgreSQL Upsert Strategy

Instead of executing 1,000 single INSERT queries per second, workers accumulate jobs over a short sliding window (e.g., 100 milliseconds) and execute a single batch query:

INSERT INTO webhook_events (event_id, provider, event_type, payload, processed_at)
SELECT * FROM UNNEST(
  $1::uuid[], $2::text[], $3::text[], $4::jsonb[], $5::timestamptz[]
)
ON CONFLICT (event_id) 
DO UPDATE SET payload = EXCLUDED.payload, processed_at = EXCLUDED.processed_at;

This batching transformation reduces database round-trips by up to 99%, dropping CPU consumption on PostgreSQL instances.

To integrate high-throughput event processing with external applications, explore our integrations & software API services.


Step-by-Step Code Blueprint

The following implementation demonstrates an ingestion gateway written in Fastify paired with a BullMQ queue processor and PostgreSQL client.

Ingestion Gateway API (gateway.js)

import Fastify from 'fastify';
import crypto from 'crypto';
import { Queue } from 'bullmq';
import Redis from 'ioredis';

const fastify = Fastify({ logger: true });
const redisConnection = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
const webhookQueue = new Queue('incoming-webhooks', { connection: redisConnection });
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || 'whsec_secret_key_8f92a3';

fastify.addContentTypeParser('application/json', { parseAs: 'buffer' }, (req, body, done) => {
  req.rawBody = body;
  try { done(null, JSON.parse(body.toString())); } catch (err) { done(err, null); }
});

fastify.post('/api/webhooks/v1/ingest', async (request, reply) => {
  const signature = request.headers['x-webhook-signature'];
  if (!signature) return reply.status(401).send({ error: 'Missing signature header' });

  const hmac = crypto.createHmac('sha256', WEBHOOK_SECRET);
  const digest = hmac.update(request.rawBody).digest('hex');
  if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest))) {
    return reply.status(403).send({ error: 'Invalid signature' });
  }

  const eventId = request.body.id || request.headers['x-request-id'];
  await webhookQueue.add(
    'process-event',
    { eventId, eventType: request.body.type, payload: request.body, receivedAt: new Date().toISOString() },
    { jobId: eventId, attempts: 5, backoff: { type: 'exponential', delay: 2000 }, removeOnComplete: true }
  );

  return reply.status(202).send({ status: 'accepted', eventId });
});

fastify.listen({ port: 3000, host: '0.0.0.0' });

Queue Worker Processor (worker.js)

import { Worker } from 'bullmq';
import Redis from 'ioredis';
import pg from 'pg';

const redisClient = new Redis(process.env.REDIS_URL || 'redis://localhost:6379');
const dbPool = new pg.Pool({ connectionString: process.env.DATABASE_URL, max: 20 });

const worker = new Worker(
  'incoming-webhooks',
  async (job) => {
    const { eventId, eventType, payload, receivedAt } = job.data;
    const lockKey = `webhook:idempotency:${eventId}`;
    const acquired = await redisClient.set(lockKey, 'processing', 'NX', 'EX', 86400);

    if (!acquired) return { skipped: true, eventId };

    try {
      const query = `
        INSERT INTO webhook_events (event_id, event_type, payload, received_at, status)
        VALUES ($1, $2, $3, $4, 'processed')
        ON CONFLICT (event_id) DO NOTHING;
      `;
      await dbPool.query(query, [eventId, eventType, JSON.stringify(payload), receivedAt]);
      await redisClient.set(lockKey, 'completed', 'EX', 86400);
      return { success: true, eventId };
    } catch (error) {
      await redisClient.del(lockKey);
      throw error;
    }
  },
  { connection: redisClient, concurrency: 50 }
);

Managed Webhook Platforms vs Self-Hosted Infrastructure

Engineering teams must decide whether to build a self-hosted architecture or utilize managed platforms.

Platform Comparison Matrix

| Feature / Metric | Self-Hosted (Fastify + BullMQ) | Managed Platform (Hookdeck / Svix) | AWS Native (SQS + EventBridge) | | --- | --- | --- | --- | | Ingestion Control | Custom control over middleware | Pre-built SaaS proxy | Serverless architecture | | Operational Effort | Medium (Managing Redis & K8s) | Zero infrastructure management | Low (Managed services) | | Signature Verification | Custom code per provider | Pre-built for 100+ providers | Requires Lambda Authorizers | | Alerting & UI | Custom Prometheus/Grafana | Built-in UI dashboards | CloudWatch Alarms |

Vendor Pricing Summary

When evaluating managed options versus self-hosted server deployments:


Monitoring, Metrics, and Alert Triggers

A reliable high volume webhook processing engine requires continuous telemetry to detect bottlenecks before queue saturation occurs:

  1. Queue Depth and Consumer Lag: Track total pending jobs in the queue. Trigger scaling when queue depth increases continuously over 5 minutes.
  2. Ingestion Latency (p99): Duration between HTTP request receipt and HTTP 202 response. P99 latency exceeding 50ms indicates event loop blockages.
  3. Dead Letter Queue (DLQ) Accumulation: Any DLQ accumulation rate exceeding 5 events per minute should trigger a alert to engineering.

To build monitoring views and operational displays for your backend events, explore our custom dashboard development services.


Architecture Mistakes to Avoid

  1. Executing Synchronous Database Writes in the Webhook Handler: Processing database operations directly inside the HTTP POST endpoint blocks incoming request threads.
  2. Neglecting HMAC Signature Validation Before Enqueueing: Failing to verify signatures at the gateway layer allows unauthorized payloads into your queue.
  3. Omitting Idempotency Keys: Assuming webhook providers deliver events exactly once causes duplicate data insertion during retries.
  4. Unbounded Worker Concurrency: Setting worker concurrency too high without connection pool limiters crashes PostgreSQL instances.
  5. Lack of Dead Letter Queue (DLQ) Monitoring: Failing to monitor DLQ event accumulation leads to silent data loss.

Frequently Asked Questions

How do I handle 100k events per minute without dropping incoming requests?

Deploy a stateless API Gateway layer using Fastify or Go that performs signature validation and enqueues events directly into Redis or SQS. Return an HTTP 202 Accepted response within 30 milliseconds.

What is the ideal HTTP response status code for incoming webhooks?

Use HTTP 202 Accepted. This status code signals to the sending platform that the webhook payload has been received and accepted for asynchronous processing.

How long should idempotency keys be retained in Redis?

Retain idempotency keys in Redis for 24 to 72 hours using key expiration (TTL). Most major webhook senders complete retry cycles within 24 hours.

Should I choose managed webhook infrastructure or build a self-hosted pipeline?

Choose a managed platform like Hookdeck or Svix for turn-key signature verification and event replay dashboards. Choose self-hosted Fastify and BullMQ if you have strict compliance requirements or process high volumes where SaaS pricing is cost-prohibitive.


Scale Your Webhook Backend with Sharcon

If your application handles expanding integration demands or experiences performance bottlenecks during peak webhook traffic, Sharcon designs resilient, event-driven backends built for high throughput.

Contact our backend engineering team to architect a scalable API gateway and queue infrastructure tailored to your stack.

Max Lebedev

Max Lebedev

CEO of Sharcon LLC

15+ years in marketing and development. Leading a team of 30+ professionals at Sharcon.