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 redisUse 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=6001Subscribe 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
- The client receives
order.createdin the console. - The HTTP publish returns success.
- If push is configured, the push publish returns a
publish_id. - Metrics under
/metricsshow connection and publish counters moving.
Debug checkpoints
Use this table when the first loop does not behave as expected.
| Symptom | Check | Fix |
|---|---|---|
| WebSocket connection fails | Browser devtools shows a failed request to /app/app-key. | Confirm wsHost, wsPort, forceTLS, and enabledTransports match the local server. |
| Subscribe succeeds but no event arrives | The 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 auth | Auth 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 duplicates | The request does not include a stable idempotency key. | Derive keys from business identifiers such as order-created-ord_123. |
| Metrics do not move | You 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.