Sockudo
Getting Started

First connection

Connect a realtime client, subscribe to a channel, and publish the first event through a trusted backend.

This guide proves the full loop: Sockudo accepts a WebSocket connection, the client subscribes, and a server-side SDK publishes an event over the HTTP API.

Start Sockudo

docker compose up sockudo redis

Use the default development app credentials:

export SOCKUDO_APP_ID=app-id
export SOCKUDO_APP_KEY=app-key
export SOCKUDO_APP_SECRET=app-secret
export SOCKUDO_HOST=127.0.0.1
export SOCKUDO_PORT=6001

Subscribe from JavaScript

import Sockudo from "@sockudo/client";

const client = new Sockudo("app-key", {
  wsHost: "127.0.0.1",
  wsPort: 6001,
  forceTLS: false,
  enabledTransports: ["ws"],
  protocolVersion: 2,
});

const channel = client.subscribe("orders");

channel.bind("order.created", (payload) => {
  console.log("received", payload);
});

Protocol V1 clients use the same server with Pusher-compatible options:

import Pusher from "pusher-js";

const pusher = new Pusher("app-key", {
  wsHost: "127.0.0.1",
  wsPort: 6001,
  forceTLS: false,
  cluster: "local",
  enabledTransports: ["ws"],
});

pusher.subscribe("orders").bind("order.created", console.log);

Publish from Node.js

import { Sockudo } from "sockudo";

const sockudo = new Sockudo({
  appId: "app-id",
  key: "app-key",
  secret: "app-secret",
  host: "127.0.0.1",
  port: 6001,
  useTLS: false,
});

await sockudo.trigger("orders", "order.created", {
  id: "ord_123",
  total: 42_00,
});

Publish over raw HTTP

Server SDKs are preferred because they handle signing, but the underlying API is simple:

curl -X POST "http://127.0.0.1:6001/apps/app-id/events" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "order.created",
    "channel": "orders",
    "data": {"id": "ord_123", "total": 4200}
  }'

Production requests must include Sockudo/Pusher HMAC authentication query parameters. Use a server SDK unless you are implementing a new SDK.

Use idempotency for retries

When a backend may retry a publish after a timeout, attach an idempotency key. Sockudo deduplicates matching keys inside the configured window.

await sockudo.trigger(
  "orders",
  "order.created",
  { id: "ord_124" },
  { idempotency_key: "order-created-ord_124" },
);

Add push notification fanout

Realtime events and push notifications are complementary. Use WebSockets for connected clients, and push for devices that are offline, backgrounded, or outside the active channel session.

await sockudo.publishPush({
  recipients: [{ type: "channel", channel: "orders" }],
  payload: {
    title: "Order created",
    body: "Order ord_124 is ready for review",
    data: { order_id: "ord_124" },
  },
  sync: false,
});

Push publishes should be async in production. Expect 202 Accepted and track the returned publish_id.

Expected result

  1. The client receives order.created in the console.
  2. The HTTP publish returns success.
  3. If push is configured, the push publish returns a publish_id.
  4. Metrics under /metrics show connection and publish counters moving.

Debug checkpoints

Use this table when the first loop does not behave as expected.

SymptomCheckFix
WebSocket connection failsBrowser devtools shows a failed request to /app/app-key.Confirm wsHost, wsPort, forceTLS, and enabledTransports match the local server.
Subscribe succeeds but no event arrivesThe backend publish may target a different app, channel, or event name.Reuse the same app-key, app-id, channel, and event name from the snippets above.
Private or presence channels reject authAuth signatures are generated on a trusted backend and include the exact socket ID and channel name.Use a server SDK for channel auth before writing custom signing code.
Retried publishes create duplicatesThe request does not include a stable idempotency key.Derive keys from business identifiers such as order-created-ord_123.
Metrics do not moveYou may be checking the wrong process, port, or app credentials.Query /up, then scrape :9601/metrics while publishing a fresh event.

When debugging compatibility, first prove the same event works with a public channel. Then add private auth, presence user data, Protocol V2 options, history, push, or mutations one feature at a time.

On this page