Sockudo
Server

Webhooks

Pusher-compatible webhook delivery with batching, filtering, and Lambda support.

Sockudo sends webhooks to notify your backend when channel and presence events occur. Webhooks are Pusher-compatible - the same payload format, signing mechanism, and event types.

How It Works

  1. An event occurs (channel occupied, member joined, client event, etc.).
  2. Sockudo matches the event against your app's webhook definitions.
  3. A job is pushed to the queue.
  4. Queue workers dispatch HTTP requests (or Lambda invocations) asynchronously.

This means webhook delivery never blocks WebSocket message handling.

Configuring Webhooks

Webhooks are defined per-app in the webhooks field:

{
  "app_manager": {
    "driver": "memory",
    "array": {
      "apps": [
        {
          "id": "my-app",
          "key": "my-key",
          "secret": "my-secret",
          "enabled": true,
          "webhooks": [
            {
              "url": "https://your-backend.com/webhooks/sockudo",
              "event_types": ["channel_occupied", "channel_vacated", "member_added", "member_removed"]
            }
          ]
        }
      ]
    }
  }
}

Event Types

EventTrigger
channel_occupiedFirst subscriber joins a channel
channel_vacatedLast subscriber leaves a channel
member_addedUser joins a presence channel
member_removedUser leaves a presence channel
client_eventClient sends an event on a private/presence channel

Webhook Payload

Sockudo sends a JSON payload compatible with the Pusher webhook format:

{
  "time_ms": 1707744000000,
  "events": [
    {
      "name": "channel_occupied",
      "channel": "presence-chat"
    }
  ]
}

For presence events, additional fields are included:

{
  "time_ms": 1707744000000,
  "events": [
    {
      "name": "member_added",
      "channel": "presence-chat",
      "user_id": "user-123"
    }
  ]
}

Request Signing

Each webhook request includes headers for verification:

HeaderDescription
Content-Typeapplication/json
X-Pusher-KeyYour app key
X-Pusher-SignatureHMAC-SHA256 hex digest of the body, signed with your app secret

Verifying Signatures

On your backend, verify the signature to ensure the request came from Sockudo:

const crypto = require('crypto');

function verifyWebhook(body, signature, appSecret) {
  const expected = crypto
    .createHmac('sha256', appSecret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Webhook Filtering

You can filter which channels trigger a webhook using the filter field:

{
  "webhooks": [
    {
      "url": "https://backend.com/presence-hooks",
      "event_types": ["member_added", "member_removed"],
      "filter": {
        "channel_prefix": "presence-"
      }
    },
    {
      "url": "https://backend.com/chat-hooks",
      "event_types": ["channel_occupied", "channel_vacated"],
      "filter": {
        "channel_prefix": "private-chat-"
      }
    }
  ]
}
Filter FieldDescription
channel_prefixOnly match channels starting with this string
channel_suffixOnly match channels ending with this string
channel_patternRegex pattern to match channel names

Custom Headers

Add custom headers to webhook requests for authentication or routing:

{
  "webhooks": [
    {
      "url": "https://backend.com/hooks",
      "event_types": ["channel_occupied"],
      "headers": {
        "Authorization": "Bearer my-token",
        "X-Custom-Header": "value"
      }
    }
  ]
}

Lambda Webhooks

Instead of HTTP endpoints, you can invoke AWS Lambda functions directly:

{
  "webhooks": [
    {
      "lambda": {
        "function_name": "my-webhook-handler",
        "region": "us-east-1"
      },
      "event_types": ["channel_occupied", "channel_vacated"]
    }
  ]
}
Lambda webhook support requires the lambda feature flag at compile time.

Batching

Sockudo can batch multiple events into a single webhook delivery to reduce HTTP overhead:

{
  "webhooks": {
    "batching": {
      "enabled": true,
      "duration": 50
    }
  }
}
SettingEnv VarDefaultDescription
enabledWEBHOOK_BATCHING_ENABLEDtrueEnable batching
durationWEBHOOK_BATCHING_DURATION50Batch window in milliseconds

When batching is enabled, events are collected for duration ms before being dispatched as a single job. This means a burst of channel events (e.g., multiple users joining at once) gets sent as one webhook request with multiple events in the events array.

Delivery Guarantees

  • Timeout: 10 seconds per webhook HTTP request.
  • Concurrency: Up to 20 concurrent webhook dispatches.
  • Retry: Depends on the queue driver:
    • Redis: Jobs are removed from the queue on consumption. Failed deliveries are not automatically retried.
    • SQS: Failed messages become visible again after visibility_timeout, providing automatic retry.
  • Deduplication: Jobs include a signature to prevent duplicate processing.

Disabling Webhooks

Set the queue driver to none to disable webhook processing entirely:

QUEUE_DRIVER=none

Or simply don't define any webhooks in your app configuration.

Copyright © 2026