MCPcopy Index your code
hub / github.com/centrifugal/centrifuge

github.com/centrifugal/centrifuge @v0.38.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.38.0 ↗ · + Follow
3,604 symbols 14,304 edges 160 files 765 documented · 21% 3 cross-repo links updated 3d agov0.38.0 · 2025-11-15★ 1,4466 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Join the chat at https://t.me/joinchat/ABFVWBE0AhkyyhREoaboXQ codecov.io GoDoc

This library has no v1 release, API may change. Before v1 release patch version updates only have backwards compatible changes and fixes, minor version updates can have backwards-incompatible API changes. Master branch can have unreleased code. Only two last Go minor versions are officially supported by this library.

The Centrifuge library is a general purpose real-time messaging library for Go programming language. Real-time messaging can help create interactive applications where events are delivered to online users with milliseconds delay. Chats apps, live comments, multiplayer games, real-time data visualizations, telemetry, collaborative tools, etc. can all be built on top of Centrifuge library.

The library is built on top of efficient client-server protocol schema and exposes various real-time oriented primitives for a developer. Centrifuge solves problems developers may come across when building complex real-time applications – like scalability to many server nodes, proper persistent connection management and invalidation, subscription multiplexing, fast reconnect with message recovery, WebSocket fallback options (without sticky sessions requirement in distributed scenario). And it all comes with ready to use client SDKs for both web and mobile development. See the full list of highlighs below.

Centrifuge library is used by:

  • Centrifugo - the main product of Centrifugal Labs. Centrifuge was decoupled into separate library from Centrifugo at some point.
  • Grafana - the most popular observability platform. Centrifuge library powers Grafana Live subsystem to stream data to panels. See cool demo of WebSocket telemetry from the Assetto Corsa racing simulator to the Grafana dashboard.

Why using Centrifuge

Centrifuge library provides a lot of top of raw WebSocket transport. Important library highlights:

  • Fast and optimized for low-latency communication with millions of client connections. See test stand with 1 million connections in Kubernetes
  • WebSocket bidirectional transport using JSON or binary Protobuf formats, both based on a strict Protobuf schema. Code generation is used to push both JSON and Protobuf serialization performance to the limits
  • Our own WebSocket emulation layer over HTTP-streaming (JSON + Protobuf) and Eventsource (JSON) without sticky sessions requirement for distributed setup
  • Possibility to use unidirectional transports without using custom Centrifuge SDK library: see examples for GRPC, EventSource(SSE), HTTP-streaming, Unidirectional WebSocket
  • Built-in horizontal scalability with Redis PUB/SUB, consistent Redis sharding, Redis Sentinel and Redis Cluster support, super-optimized Redis communication layer
  • Effective non-blocking broadcasts towards client connections using individual queues
  • Native authentication over HTTP middleware or custom token-based (ex. JWT)
  • Channel concept to broadcast message to all active subscribers
  • Client-side and server-side channel subscriptions
  • Bidirectional asynchronous message communication, RPC calls, builtin PING/PONG
  • Presence information for channels (show all active clients in a channel)
  • History information for channels (ephemeral streams with size and TTL retention)
  • Join/leave events for channels (aka client goes online/offline)
  • Possibility to register a custom PUB/SUB Broker and PresenceManager implementations
  • Option to register custom Transport, like Centrifugo does with WebTransport
  • Message recovery mechanism for channels to survive PUB/SUB delivery problems, short network disconnects or node restart
  • Cache channels – a way to quickly deliver latest publication from channel history to the client upon subscription
  • Delta compression using Fossil algorithm for publications inside a channel to reduce bandwidth usage
  • Support for client-supplied publication filters to drop unnecessary channel publications on the server side
  • Per-client and per-channel batching controls for reduced system calls and better CPU utilization
  • Out-of-the-box observability using Prometheus instrumentation
  • Client SDKs for main application environments all following single behaviour spec (see list of SDKs below).

Real-time SDK

For bidirectional communication between a client and a Centrifuge-based server we have a set of official client real-time SDKs:

These SDKs abstract asynchronous communication complexity from the developer: handle framing, reconnect with backoff, timeouts, multiplex channel subscriptions over single connection, etc.

If you opt for a unidirectional communication then you may leverage Centrifuge possibilities without any specific SDK on client-side - simply by using native browser API or GRPC-generated code. See examples of unidirectional communication over GRPC, EventSource(SSE), HTTP-streaming, WebSocket.

Explore Centrifuge

Installation

go get github.com/centrifugal/centrifuge

Tutorial

Let's take a look on how to build the simplest real-time chat with Centrifuge library. Clients will be able to connect to a server over Websocket, send a message into a channel and this message will be instantly delivered to all active channel subscribers. On a server side we will accept all connections and will work as a simple PUB/SUB proxy without worrying too much about permissions. In this example we will use Centrifuge Javascript client (centrifuge-js) on a frontend.

Start a new Go project and create main.go:

package main

import (
    "log"
    "net/http"

    // Import this library.
    "github.com/centrifugal/centrifuge"
)

// Authentication middleware example. Centrifuge expects Credentials
// with current user ID set. Without provided Credentials client
// connection won't be accepted. Another way to authenticate connection
// is reacting to node.OnConnecting event where you may authenticate
// connection based on a custom token sent by a client in first protocol
// frame. See _examples folder in repo to find real-life auth samples
// (OAuth2, Gin sessions, JWT etc).
func auth(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := r.Context()
        // Put authentication Credentials into request Context.
        // Since we don't have any session backend here we simply
        // set user ID as empty string. Users with empty ID called
        // anonymous users, in real app you should decide whether
        // anonymous users allowed to connect to your server or not.
        cred := &centrifuge.Credentials{
            UserID: "",
        }
        newCtx := centrifuge.SetCredentials(ctx, cred)
        r = r.WithContext(newCtx)
        h.ServeHTTP(w, r)
    })
}

func main() {
    // Node is the core object in Centrifuge library responsible for
    // many useful things. For example Node allows publishing messages
    // into channels with its Publish method. Here we initialize Node
    // with Config which has reasonable defaults for zero values.
    node, err := centrifuge.New(centrifuge.Config{})
    if err != nil {
        log.Fatal(err)
    }

    // Set ConnectHandler called when client successfully connected to Node.
    // Your code inside a handler must be synchronized since it will be called
    // concurrently from different goroutines (belonging to different client
    // connections). See information about connection life cycle in library readme.
    // This handler should not block – so do minimal work here, set required
    // connection event handlers and return.
    node.OnConnect(func(client *centrifuge.Client) {
        // In our example transport will always be Websocket but it can be different.
        transportName := client.Transport().Name()
        // In our example clients connect with JSON protocol but it can also be Protobuf.
        transportProto := client.Transport().Protocol()
        log.Printf("client connected via %s (%s)", transportName, transportProto)

        // Set SubscribeHandler to react on every channel subscription attempt
        // initiated by a client. Here you can theoretically return an error or
        // disconnect a client from a server if needed. But here we just accept
        // all subscriptions to all channels. In real life you may use a more
        // complex permission check here. The reason why we use callback style
        // inside client event handlers is that it gives a possibility to control
        // operation concurrency to developer and still control order of events.
        client.OnSubscribe(func(e centrifuge.SubscribeEvent, cb centrifuge.SubscribeCallback) {
            log.Printf("client subscribes on channel %s", e.Channel)
            cb(centrifuge.SubscribeReply{}, nil)
        })

        // By default, clients can not publish messages into channels. By setting
        // PublishHandler we tell Centrifuge that publish from a client-side is
        // possible. Now each time client calls publish method this handler will be
        // called and you have a possibility to validate publication request. After
        // returning from this handler Publication will be published to a channel and
        // reach active subscribers with at most once delivery guarantee. In our simple
        // chat app we allow everyone to publish into any channel but in real case
        // you may have more validation.
        client.OnPublish(func(e centrifuge.PublishEvent, cb centrifuge.PublishCallback) {
            log.Printf("client publishes into channel %s: %s", e.Channel, string(e.Data))
            cb(centrifuge.PublishReply{}, nil)
        })

        // Set Disconnect handler to react on client disconnect events.
        client.OnDisconnect(func(e centrifuge.DisconnectEvent) {
            log.Printf("client disconnected")
        })
    })

    // Run node. This method does not block. See also node.Shutdown method
    // to finish application gracefully.
    if err := node.Run(); err != nil {
        log.Fatal(err)
    }

    // Now configure HTTP routes.

    // Serve Websocket connections using WebsocketHandler.
    wsHandler := centrifuge.NewWebsocketHandler(node, centrifuge.WebsocketConfig{})
    http.Handle("/connection/websocket", auth(wsHandler))

    // The second route is for serving index.html file.
    http.Handle("/", http.FileServer(http.Dir("./")))

    log.Printf("Starting server, visit http://localhost:8000")
    if err := http.ListenAndServe(":8000", nil); err != nil {
        log.Fatal(err)
    }
}

Also create file index.html near main.go with content:

```html

Centrifuge chat example

Extension points exported contracts — how you extend this code

Core symbols most depended-on inside this repo

Shape

Function 1,812
Method 1,390
Struct 292
FuncType 42
Class 28
Interface 21
TypeAlias 19

Languages

Go72%
TypeScript28%

Modules by API surface

_examples/recovery_mode_cache/d3.v7.min.js839 symbols
client_test.go166 symbols
_examples/recovery_mode_cache/centrifuge.js150 symbols
client.go149 symbols
_examples/unidirectional_grpc/clientproto/uni.pb.go149 symbols
internal/controlpb/control.pb.go141 symbols
node.go103 symbols
node_test.go85 symbols
broker_redis_test.go66 symbols
events.go62 symbols
internal/websocket/conn.go60 symbols
internal/controlpb/control_vtproto.pb.go60 symbols

For agents

$ claude mcp add centrifuge \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page