skills/community/centrifugo/SKILL.md
Centrifugo real-time messaging server expert for WebSocket PUB/SUB, channel management, JWT authentication, event proxying, and horizontal scaling with Redis/NATS. Use when: centrifugo, centrifugal, real-time messaging, websocket pubsub, channel subscriptions, real-time notifications, live updates, presence, history recovery, server-sent events integration, real-time transport layer. Do not use for: general WebSocket programming without Centrifugo, Socket.IO, Pusher SDK, or other real-time frameworks.
npx skillsauth add pedronauck/skills centrifugoInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Centrifugo is a self-hosted, language-agnostic real-time messaging server. It handles persistent connections (WebSocket, SSE, HTTP-streaming, WebTransport, GRPC) and broadcasts messages via a channel-based PUB/SUB model. The application backend publishes to channels via Server API; Centrifugo delivers to online subscribers instantly.
Backend App ──(HTTP/GRPC Server API)──> Centrifugo Cluster ──(WebSocket/SSE)──> Clients
│
Redis/NATS Broker
(for multi-node)
Key principle: All user-generated data flows through the application backend first (validate, persist, then publish to Centrifugo). Centrifugo is the transport layer, not the source of truth.
Identify the real-time feature being built and select the appropriate pattern:
Generate a minimal configuration:
centrifugo genconfig # Creates config.json
Or use Docker:
docker run -p 8000:8000 centrifugo/centrifugo:v6 centrifugo
Essential configuration structure (JSON, YAML, or TOML supported):
{
"client": {
"token": {
"hmac_secret_key": "<SECRET>"
},
"allowed_origins": ["http://localhost:3000"]
},
"http_api": {
"key": "<API_KEY>"
},
"channel": {
"without_namespace": {
"allow_subscribe_for_client": true
}
}
}
Read references/configuration.md for the full configuration reference including TLS, admin UI, environment variables, and advanced options.
Centrifugo authenticates clients via JWT or connect proxy.
JWT approach (recommended for most cases):
sub (user ID) and exp claims, signed with the configured HMAC/RSA/ECDSA key.# Backend: generate connection JWT (Python example)
import jwt, time
token = jwt.encode(
{"sub": "user123", "exp": int(time.time()) + 3600},
"<HMAC_SECRET>", algorithm="HS256"
)
// Client: connect with token
const client = new Centrifuge("ws://localhost:8000/connection/websocket", {
token: "<JWT_TOKEN>",
});
client.connect();
Connect proxy approach (alternative):
Read references/authentication.md for JWT claims, token refresh, proxy auth, and channel-level authorization tokens.
Channels are ephemeral strings that serve as message pathways. Use namespaces to apply different behaviors.
Naming conventions:
chat:room-123 — namespace chat, channel for room 123notifications:user#42 — user-limited channel (only user 42 can subscribe)$private:secret — private channel prefix (requires subscription token)Namespace configuration:
{
"channel": {
"namespaces": [
{
"name": "chat",
"presence": true,
"history_size": 50,
"history_ttl": "300s",
"force_recovery": true,
"join_leave": true
},
{
"name": "notifications",
"allow_user_limited_channels": true
}
]
}
}
Read references/channels.md for all channel options, namespace rules, and special channel prefixes.
Use HTTP or GRPC to publish messages from the application backend.
HTTP API — POST to /api/<method> with X-API-Key header:
# Publish to a channel
curl -X POST -H "X-API-Key: <KEY>" -H "Content-Type: application/json" \
-d '{"channel": "chat:room-1", "data": {"text": "hello"}}' \
http://localhost:8000/api/publish
# Broadcast to multiple channels
curl -X POST -H "X-API-Key: <KEY>" -H "Content-Type: application/json" \
-d '{"channels": ["user:1", "user:2"], "data": {"text": "hello"}}' \
http://localhost:8000/api/broadcast
Available API methods: publish, broadcast, subscribe, unsubscribe, disconnect, refresh, presence, presence_stats, history, history_remove, channels, info, batch.
Read references/server-api.md for all method signatures, request/response schemas, and HTTP API library links.
Official SDKs: centrifuge-js (browser/Node/React Native), centrifuge-go, centrifuge-dart (Flutter), centrifuge-swift (iOS), centrifuge-java (Android), centrifuge-python.
JavaScript client pattern:
import { Centrifuge } from "centrifuge";
const client = new Centrifuge("ws://localhost:8000/connection/websocket", {
token: "<JWT>",
});
// Connection state handlers
client.on("connecting", ctx => console.log("connecting", ctx));
client.on("connected", ctx => console.log("connected", ctx));
client.on("disconnected", ctx => console.log("disconnected", ctx));
// Subscribe to channel
const sub = client.newSubscription("chat:room-1");
sub.on("publication", ctx => {
console.log("received:", ctx.data);
});
sub.on("subscribing", ctx => console.log("subscribing", ctx));
sub.on("subscribed", ctx => console.log("subscribed", ctx));
sub.subscribe();
client.connect();
Client states: disconnected -> connecting -> connected (auto-reconnect with exponential backoff).
Subscription states: unsubscribed -> subscribing -> subscribed (auto-resubscribe on reconnect).
Read references/client-sdk.md for all SDK patterns, token refresh, presence/history from client, RPC calls, and Protobuf mode.
Proxy client events to the backend for validation and custom logic.
Supported proxy events:
connect — authenticate connections without JWTrefresh — extend client sessionssubscribe — validate channel accesspublish — validate publications from clientsrpc — handle custom client-to-server callssub_refresh — extend subscription sessions{
"client": {
"proxy": {
"connect": {
"enabled": true,
"endpoint": "http://backend:3000/centrifugo/connect"
},
"rpc": {
"enabled": true,
"endpoint": "http://backend:3000/centrifugo/rpc"
}
}
},
"channel": {
"namespaces": [
{
"name": "chat",
"proxy": {
"subscribe": {
"enabled": true,
"endpoint": "http://backend:3000/centrifugo/subscribe"
},
"publish": {
"enabled": true,
"endpoint": "http://backend:3000/centrifugo/publish"
}
}
}
]
}
}
Read references/proxy.md for proxy request/response schemas, GRPC proxy, header forwarding, and timeout configuration.
Memory engine (default): Single node only. Fast, no dependencies. Suitable for development and small deployments.
Redis engine: Multi-node clusters. Messages published on any node reach all subscribers.
{
"engine": {
"type": "redis",
"redis": {
"address": "redis://localhost:6379"
}
}
}
Supports Redis Sentinel, Redis Cluster, consistent sharding across multiple Redis instances, and Redis-compatible storages (Valkey, DragonflyDB, KeyDB, AWS ElastiCache).
NATS broker: Alternative for PUB/SUB only (no history/presence persistence).
Read references/engines.md for Redis Sentinel/Cluster setup, sharding, NATS configuration, and separate broker/presence manager configuration.
History allows caching recent publications per channel. Recovery automatically restores missed messages after reconnection.
{
"channel": {
"namespaces": [
{
"name": "chat",
"history_size": 100,
"history_ttl": "600s",
"force_recovery": true,
"force_positioning": true
}
]
}
}
history_size + history_ttl: Define retention window.force_recovery: Clients automatically recover missed messages on reconnect.force_positioning: Detect publication gaps.references/channels.md for details.Centrifugo exposes Prometheus metrics at /metrics and supports structured logging.
{
"log_level": "info",
"prometheus": {
"enabled": true
},
"health": {
"enabled": true
}
}
Metrics include: connections, subscriptions, publications, API calls, transport stats, and engine stats.
History is an ephemeral hot cache designed to reduce database load during reconnect storms. Always maintain a primary application database.
Design with graceful degradation. If Centrifugo goes down, the application should still function (just without real-time updates). Return data in API responses, not only via channels.
allowed_origins in productionEmpty allowed_origins blocks all browser connections. Configure it with the exact origins of the frontend application.
Always validate client publications through either:
Namespaces provide granular control over channel behavior and permissions. Define a namespace for each real-time feature.
Set reasonable exp claims in JWTs. Too short = excessive refresh requests. Too long = delayed user deactivation. Implement the token refresh callback in client SDKs.
102: unknown channel — verify the namespace is defined in configuration.103: permission denied — check channel permissions (allow_subscribe_for_client, subscription JWT, or subscribe proxy).allowed_origins, JWT validity/expiration, and network connectivity.redis://, rediss:// for TLS, redis+sentinel:// for Sentinel, redis+cluster:// for Cluster).Centrifugo integrates well with any backend language/framework. Common setups include:
centrifuge npm package for server-side operations.centrifuge Go library directly or the Centrifugo HTTP/GRPC API.pycent library or direct HTTP API calls.phpcent library.For the JavaScript client SDK (centrifuge-js), install via npm:
npm install centrifuge
# or
bun add centrifuge
testing
Assess DDD fit; discover domains with EventStorming, define language and bounded contexts, and design aggregates, value objects, events, and repositories. Excludes architecture-only audits, product specs, and CQRS/Event Sourcing catalogs.
development
Build terminal UIs with ratatui following 2026 Rust best practices. Use when: (1) Creating new TUI apps, (2) Adding widgets/layouts, (3) Keyboard navigation/state management, (4) Image integration via ratatui-image, (5) Async event handling, (6) Release optimization. Covers v0.30.0+ API, Elm Architecture, StatefulWidget, color-eyre.
development
Find 10x product opportunities and high-leverage improvements. Use when user wants strategic product thinking, mentions '10x', wants to find high-impact features, or says 'what would make this 10x better', 'product strategy', or 'what should we build next'.
development
You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.