• Pricing
  • Blog
Sign InGet Started
  1. Guides
  2. /
  3. Webhook Patterns

Webhook Patterns & Best Practices

Build reliable event-driven workflows. Learn proven patterns for webhook security, error handling, and scalability.

Start Building
12 min readIntermediateLast updated: December 2024

In This Guide

  1. 1. Essential Patterns
  2. 2. Common Use Cases
  3. 3. What's Next
  4. 4. FAQ

6 Essential Webhook Patterns

Implement these patterns to build webhook integrations that are secure, reliable, and maintainable.

1

Signature Verification

Always verify webhook signatures to ensure requests come from legitimate sources. Most services sign payloads with HMAC-SHA256.

// Verify webhook signature
const signature = request.headers['x-signature'];
const payload = JSON.stringify(request.body);
const expected = crypto
  .createHmac('sha256', webhookSecret)
  .update(payload)
  .digest('hex');

if (signature !== expected) {
  throw new Error('Invalid signature');
}

Key Points:

  • Store webhook secrets in environment variables
  • Use constant-time comparison to prevent timing attacks
  • Log failed verification attempts for security monitoring
2

Idempotency Handling

Webhooks may be delivered multiple times. Use idempotency keys to ensure each event is processed only once.

// Check if event already processed
const eventId = request.body.id;
const processed = await db.webhookEvents.findOne({ eventId });

if (processed) {
  return { status: 'already_processed' };
}

// Process event and store ID
await processEvent(request.body);
await db.webhookEvents.create({ eventId, processedAt: new Date() });

Key Points:

  • Store event IDs with TTL for automatic cleanup
  • Return 200 even for duplicate events to prevent retries
  • Include idempotency key in your processing logic
3

Async Processing

Respond quickly to webhook requests (within 30 seconds) by queuing work for background processing.

// Respond immediately, process later
app.post('/webhook', async (req, res) => {
  // Validate quickly
  if (!isValidSignature(req)) {
    return res.status(401).send('Invalid');
  }

  // Queue for background processing
  await queue.add('process-webhook', {
    payload: req.body,
    receivedAt: Date.now()
  });

  // Respond immediately
  res.status(200).send('Accepted');
});

Key Points:

  • Most services timeout after 30 seconds
  • Use message queues (Redis, SQS, etc.) for reliability
  • Implement dead letter queues for failed jobs
4

Payload Validation

Validate webhook payloads against expected schemas to catch malformed data early and prevent downstream errors.

// Validate payload structure
const schema = z.object({
  event: z.enum(['created', 'updated', 'deleted']),
  data: z.object({
    id: z.string(),
    timestamp: z.string().datetime(),
    attributes: z.record(z.unknown())
  })
});

const result = schema.safeParse(request.body);
if (!result.success) {
  console.error('Invalid payload:', result.error);
  return res.status(400).send('Invalid payload');
}

Key Points:

  • Use Zod, Joi, or similar for schema validation
  • Log validation failures for debugging
  • Be lenient with unknown fields for forward compatibility
5

Retry Logic & Backoff

When sending webhooks, implement exponential backoff to handle temporary failures gracefully.

// Exponential backoff for retries
async function sendWithRetry(url, payload, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, {
        method: 'POST',
        body: JSON.stringify(payload),
        headers: { 'Content-Type': 'application/json' }
      });

      if (response.ok) return response;
      if (response.status < 500) throw new Error('Client error');
    } catch (error) {
      const delay = Math.pow(2, attempt) * 1000;
      await sleep(delay);
    }
  }
  throw new Error('Max retries exceeded');
}

Key Points:

  • Start with short delays (1s, 2s, 4s, 8s, 16s)
  • Add jitter to prevent thundering herd
  • Set maximum retry limits and alert on failures
6

Secret Rotation

Rotate webhook secrets periodically. Support multiple active secrets during rotation windows.

// Support multiple secrets during rotation
const secrets = [
  process.env.WEBHOOK_SECRET_CURRENT,
  process.env.WEBHOOK_SECRET_PREVIOUS
].filter(Boolean);

function verifySignature(payload, signature) {
  for (const secret of secrets) {
    const expected = computeSignature(payload, secret);
    if (timingSafeEqual(signature, expected)) {
      return true;
    }
  }
  return false;
}

Key Points:

  • Rotate secrets every 90 days minimum
  • Support 2 active secrets during transition
  • Automate rotation with secret management tools

Common Webhook Use Cases

Real-world scenarios where webhooks power critical automations.

Payment Processing

Handle Stripe/PayPal payment events

payment.succeededpayment.failedrefund.created

CI/CD Pipelines

Trigger builds on code pushes

pushpull_requestdeployment

CRM Sync

Keep systems in sync on contact changes

contact.createddeal.updatedactivity.logged

E-commerce

React to order lifecycle events

order.placedorder.shippedinventory.low

What's Next?

Visual Debugging

Debug webhook workflows with visual execution traces

Export to Code

Export your webhook workflows as production TypeScript

Frequently Asked Questions

Common questions about webhook implementations.

Ready to Build Event-Driven Workflows?

Create webhook-triggered automations with visual debugging and built-in best practices.

Start FreeBrowse Templates

Beautiful API documentation that developers love.

Features

  • AI-Generated Docs
  • Interactive Playground
  • Auto-Sync
  • AI Chatbot
  • Breaking Changes
  • Code Samples
  • Custom Branding
  • Analytics

Compare

  • vs ReadMe
  • vs Swagger UI
  • vs Mintlify
  • vs Postman
  • vs Scalar

Ecosystem

  • Workflows
  • Forms
  • Marketplace
  • Integrations
  • MCP Servers
  • Digital Rooms
  • Product OS

Free Tools

  • JSON Formatter
  • JSON Validator
  • JWT Decoder
  • OpenAPI Validator
  • cURL → Code
  • YAML ↔ JSON
  • All free tools →

Resources

  • Free Developer Tools
  • Blog
  • Guides
  • API Glossary
  • Help Center
  • Support

© 2026 Modlific. All rights reserved.

Privacy PolicyTerms of Service
  • Pricing
  • Blog
Sign InGet Started
  1. Guides
  2. /
  3. Webhook Patterns

Webhook Patterns & Best Practices

Build reliable event-driven workflows. Learn proven patterns for webhook security, error handling, and scalability.

Start Building
12 min readIntermediateLast updated: December 2024

In This Guide

  1. 1. Essential Patterns
  2. 2. Common Use Cases
  3. 3. What's Next
  4. 4. FAQ

6 Essential Webhook Patterns

Implement these patterns to build webhook integrations that are secure, reliable, and maintainable.

1

Signature Verification

Always verify webhook signatures to ensure requests come from legitimate sources. Most services sign payloads with HMAC-SHA256.

// Verify webhook signature
const signature = request.headers['x-signature'];
const payload = JSON.stringify(request.body);
const expected = crypto
  .createHmac('sha256', webhookSecret)
  .update(payload)
  .digest('hex');

if (signature !== expected) {
  throw new Error('Invalid signature');
}

Key Points:

  • Store webhook secrets in environment variables
  • Use constant-time comparison to prevent timing attacks
  • Log failed verification attempts for security monitoring
2

Idempotency Handling

Webhooks may be delivered multiple times. Use idempotency keys to ensure each event is processed only once.

// Check if event already processed
const eventId = request.body.id;
const processed = await db.webhookEvents.findOne({ eventId });

if (processed) {
  return { status: 'already_processed' };
}

// Process event and store ID
await processEvent(request.body);
await db.webhookEvents.create({ eventId, processedAt: new Date() });

Key Points:

  • Store event IDs with TTL for automatic cleanup
  • Return 200 even for duplicate events to prevent retries
  • Include idempotency key in your processing logic
3

Async Processing

Respond quickly to webhook requests (within 30 seconds) by queuing work for background processing.

// Respond immediately, process later
app.post('/webhook', async (req, res) => {
  // Validate quickly
  if (!isValidSignature(req)) {
    return res.status(401).send('Invalid');
  }

  // Queue for background processing
  await queue.add('process-webhook', {
    payload: req.body,
    receivedAt: Date.now()
  });

  // Respond immediately
  res.status(200).send('Accepted');
});

Key Points:

  • Most services timeout after 30 seconds
  • Use message queues (Redis, SQS, etc.) for reliability
  • Implement dead letter queues for failed jobs
4

Payload Validation

Validate webhook payloads against expected schemas to catch malformed data early and prevent downstream errors.

// Validate payload structure
const schema = z.object({
  event: z.enum(['created', 'updated', 'deleted']),
  data: z.object({
    id: z.string(),
    timestamp: z.string().datetime(),
    attributes: z.record(z.unknown())
  })
});

const result = schema.safeParse(request.body);
if (!result.success) {
  console.error('Invalid payload:', result.error);
  return res.status(400).send('Invalid payload');
}

Key Points:

  • Use Zod, Joi, or similar for schema validation
  • Log validation failures for debugging
  • Be lenient with unknown fields for forward compatibility
5

Retry Logic & Backoff

When sending webhooks, implement exponential backoff to handle temporary failures gracefully.

// Exponential backoff for retries
async function sendWithRetry(url, payload, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, {
        method: 'POST',
        body: JSON.stringify(payload),
        headers: { 'Content-Type': 'application/json' }
      });

      if (response.ok) return response;
      if (response.status < 500) throw new Error('Client error');
    } catch (error) {
      const delay = Math.pow(2, attempt) * 1000;
      await sleep(delay);
    }
  }
  throw new Error('Max retries exceeded');
}

Key Points:

  • Start with short delays (1s, 2s, 4s, 8s, 16s)
  • Add jitter to prevent thundering herd
  • Set maximum retry limits and alert on failures
6

Secret Rotation

Rotate webhook secrets periodically. Support multiple active secrets during rotation windows.

// Support multiple secrets during rotation
const secrets = [
  process.env.WEBHOOK_SECRET_CURRENT,
  process.env.WEBHOOK_SECRET_PREVIOUS
].filter(Boolean);

function verifySignature(payload, signature) {
  for (const secret of secrets) {
    const expected = computeSignature(payload, secret);
    if (timingSafeEqual(signature, expected)) {
      return true;
    }
  }
  return false;
}

Key Points:

  • Rotate secrets every 90 days minimum
  • Support 2 active secrets during transition
  • Automate rotation with secret management tools

Common Webhook Use Cases

Real-world scenarios where webhooks power critical automations.

Payment Processing

Handle Stripe/PayPal payment events

payment.succeededpayment.failedrefund.created

CI/CD Pipelines

Trigger builds on code pushes

pushpull_requestdeployment

CRM Sync

Keep systems in sync on contact changes

contact.createddeal.updatedactivity.logged

E-commerce

React to order lifecycle events

order.placedorder.shippedinventory.low

What's Next?

Visual Debugging

Debug webhook workflows with visual execution traces

Export to Code

Export your webhook workflows as production TypeScript

Frequently Asked Questions

Common questions about webhook implementations.

Ready to Build Event-Driven Workflows?

Create webhook-triggered automations with visual debugging and built-in best practices.

Start FreeBrowse Templates

Beautiful API documentation that developers love.

Features

  • AI-Generated Docs
  • Interactive Playground
  • Auto-Sync
  • AI Chatbot
  • Breaking Changes
  • Code Samples
  • Custom Branding
  • Analytics

Compare

  • vs ReadMe
  • vs Swagger UI
  • vs Mintlify
  • vs Postman
  • vs Scalar

Ecosystem

  • Workflows
  • Forms
  • Marketplace
  • Integrations
  • MCP Servers
  • Digital Rooms
  • Product OS

Free Tools

  • JSON Formatter
  • JSON Validator
  • JWT Decoder
  • OpenAPI Validator
  • cURL → Code
  • YAML ↔ JSON
  • All free tools →

Resources

  • Free Developer Tools
  • Blog
  • Guides
  • API Glossary
  • Help Center
  • Support

© 2026 Modlific. All rights reserved.

Privacy PolicyTerms of Service