Skip to content

Releases: centrifugal/centrifugo

v6.9.6

Choose a tag to compare

@FZambia FZambia released this 14 Sep 17:29
f2e575f

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Fixes

  • A client-side subscription refresh with an already expired subscription token was accepted. The subscription's expiration time was then cleared, so the subscription never expired. Now Centrifugo closes the connection with the 3006 (subscription expired) disconnect code. The client reconnects, gets a token expired error on resubscribe and requests a new token – all official SDKs already handle this (centrifugal/centrifuge#627).
  • Fossil delta compression with recovery: when a subscribe with recovery found no missed publications, the next publication was still sent as a delta. The client had no base data for it, so it could not decode that publication or any after it. Now the first publication after such a subscribe is sent with full data (centrifugal/centrifuge#629).
  • Align fossil deltas to UTF-8 character boundaries for JSON clients centrifugal/centrifuge#630. For a change inside a multi-byte character it copies the first bytes of the character from the previous data and inserts the rest. The inserted bytes aren't valid UTF-8, json.Escape replaces them with U+FFFD, and the client fails to apply the delta. The fix eliminates this.

Miscellaneous

  • This release is built with Go 1.26.8.
  • Dependency updates.
  • See also the corresponding Centrifugo PRO release.

v6.9.5

Choose a tag to compare

@FZambia FZambia released this 13 Sep 05:53
34560b8

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Improvements

  • Slightly less work when recording centrifugo_client_ping_pong_duration_seconds – the histogram observer is now cached instead of being looked up on every pong.

Fixes

  • Fix possible panic in the channel options cache on long-running nodes. Its internal counter overflowed int32 after enough cache misses, which gave a negative slot index and crashed the node with index out of range (#1227).
  • Map subscriptions: the subscribe reply did not include expires/ttl, so clients could not refresh the subscription token in time. Also, if the map state was loaded in several pages, the client's subscription refresh was rejected with a bad request disconnect. A subscription whose expiration time was already in the past was accepted (centrifugal/centrifuge#626).
  • allowed_origins patterns with upper-case letters (e.g. https://App.Example.com) never matched, because the request Origin was lower-cased before matching and the pattern was not. Patterns are now matched case-insensitively (#1230).
  • client_name was ignored for Redis used by redis_stream async consumers (#1229).
  • PostgreSQL engine: handle one more case of several nodes creating the schema at the same time – a node could fail on start with type ... already exists (SQLSTATE 42710) (#1231).
  • The centrifugo_client_subscriptions_accepted metric was registered but never incremented, so it always showed zero (centrifugal/centrifuge#622).
  • The client closed or unsubscribed after adding subscription message is now logged at info level instead of error. It happens when a client goes away while its subscription is still being set up – this is expected and is not a server error (centrifugal/centrifuge#621).

Miscellaneous

  • We’ve updated the official Centrifugo dashboard. It covers all exposed metrics in v6.9.4, avoids deprecated Prometheus summaries, and includes descriptions for all panels. You can download it from grafana.com. See also Centrifugo's observability docs
  • This release is built with Go 1.26.8.
  • Dependency updates.
  • See also the corresponding Centrifugo PRO release.

v6.9.4

Choose a tag to compare

@FZambia FZambia released this 07 Sep 05:07
4b85416

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Improvements

  • New centrifugo_transport_frame_size metric – a histogram of frame sizes received from client connections. One frame may contain several commands, so this can't be calculated from the existing per-command counters. Helps to choose a good value for websocket.message_size_limit, which is applied to the whole frame (centrifugal/centrifuge#620).
  • Faster Protobuf client protocol command encoding: ~2.1x faster and ~55% less memory alloc
  • Less work on every client command: config accessors and the channel options cache no longer copy structs on each call (#1215).
  • PostgreSQL broker, map broker and controller now validate table_prefix on start. A prefix with a hyphen, space or dot used to produce a confusing syntax error inside a generated CREATE statement (#1223).

Fixes

  • Async consumers: a context.Canceled error returned by the message dispatcher was treated as a shutdown signal. In the Kafka consumer this could skip records and then commit an offset after them, losing messages. This did not happen right now in Centrifugo, but inaccurately introduced code could cause this in the future. Fixed for Kafka and SQS (#1221).
  • fix(pgoutbox): tolerate 42P07 when another node creates the partition first #1220. Thanks to @AlexeyShalaev for bringing and fixing this.
  • PostgreSQL engine: handle the case when several nodes create the schema at the same time. Before that a node which lost the race could fail to start with error initializing Postgres ... schema.
  • PostgreSQL map broker: the fast path in EnsureSchema never worked, so every node start ran the full DDL batch again. It works now and also refreshes the partition lookahead (#1223).
  • Fix a race in log throttling of the connection limit check – it could print many duplicate warnings instead of one per throttle interval (#1214).
  • Some config validation errors mentioned keys which don't exist, so it was hard to find the option to fix (#1213).
  • Admin web UI: fix uptime formatting on the Status page (centrifugal/web#71).

Miscellaneous

  • This release is built with Go 1.26.8.
  • Dependency updates.
  • See also the corresponding Centrifugo PRO release.

New Contributors

Full Changelog: v6.9.3...v6.9.4

v6.9.3

Choose a tag to compare

@FZambia FZambia released this 23 Aug 06:45
e108c4e

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Improvements

  • Faster and less allocating decoding of client commands. The command decoders are on the hot path – one is taken from the pool for every frame a client sends. The JSON decoder now reuses its buffered reader instead of allocating a new 4KB buffer per frame, and returns commands without allocating a slice per command when they fit into the read buffer. The Protobuf decoder unmarshals small messages straight out of the buffered reader instead of copying them into a scratch buffer first. Decoding a frame with a single JSON command got 62% faster with 93% less memory allocated, a frame with 8 commands – 25% faster with 67% less memory; for Protobuf the win is around 7-10% in time (centrifugal/protocol#41).
  • The message size limit is now applied to every command in a JSON frame. Previously it was only checked reliably for the first command, so subsequent commands in the same frame could exceed the configured limit (up to roughly twice it). A command of exactly the limit is still accepted wherever it sits in the frame (centrifugal/protocol#41).

Fixes

  • Fix client.connection_rate_limit: the configured value was used as the token bucket burst only, while the sustained rate was one connection per second. Centrifugo now accepts the configured number of new connections per second, keeping the configured value as the burst size too. Thanks to @moses-mbaga for the fix (#1207).
  • Shared poll: hmac_previous_secret_key_valid_until was compared against the iat claim carried inside the track signature. That value is chosen by whoever mints the signature, so anyone retaining the rotated-out key could keep producing accepted signatures indefinitely by backdating iat. The cutoff is now enforced against server time before consulting the previous verifier – the same way it works for the previous JWT HMAC key – with the iat check kept as an additional constraint inside the grace period (#1209).
  • Apply publication_data_format on all publication paths. It was only enforced for stream publishes (API publish, API broadcast, client publish), so map publish, shared poll publish and client map publish stored whatever bytes the caller sent. Data returned by publish, map publish and shared poll refresh proxies is now validated as well – a proxy can replace the data a client sent, and a shared poll refresh result reaches subscribers without ever passing through a client (#1210).

Miscellaneous

  • This release is built with Go 1.26.7.
  • Dependency updates.
  • See also the corresponding Centrifugo PRO release.

New Contributors

Full Changelog: v6.9.2...v6.9.3

v6.9.2

Choose a tag to compare

@FZambia FZambia released this 18 Aug 05:15
2db3c26

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Improvements

  • Connection runtime stability, consistency, and performance improvements coming from the underlying Centrifuge library. Under connection churn and concurrent subscribe/unsubscribe on the same channel, Centrifugo now keeps its internal subscription state consistent, fixes several resource and presence leaks, and avoids possible metric drift. The periodic presence updates also use noticeably less CPU and memory. As part of this work some internal operations became up to 500x faster under certain conditions (centrifugal/centrifuge#590).
  • Less memory allocation and garbage collection pressure on the message broadcast path. This mostly helps nodes that deliver many messages per second (centrifugal/centrifuge#598).
  • Kafka consumer: copy fetched records into a compact slice before putting them into the internal partition queue. Previously the queued records could keep the whole underlying fetch buffer in memory, so memory usage grew more than expected when a consumer was lagging behind (#1195).
  • Redis: read commands now fail within the expected time when Redis is unreachable, instead of silently retrying until Redis comes back. This makes behavior during a Redis outage predictable and matches how writes already worked (#1191 and centrifugal/centrifuge#591).
  • Redis: bound the worst-case time to detect a silently stalled connection (the peer stops replying but the TCP connection stays open) to under 5 seconds by tuning the keepalive (#1192 and centrifugal/centrifuge#592).
  • Redis: verify PUB/SUB delivery with liveness probes to detect a broken subscription connection earlier (centrifugal/centrifuge#594).
  • Add per-IP throttling of failed attempts on the admin password login endpoint (POST /admin/auth) to slow down brute-force. A valid login is not affected, even while an attack is in progress. This is best-effort protection only – the admin endpoint should still be protected at the infrastructure level (firewall rules, private network, authenticating reverse proxy) (#1204).
  • Harden the binary (Protobuf) protocol frame decoder so that a crafted length prefix can no longer make the server allocate too much memory. The configured message size limit is now always applied when reading client commands (#1203 and centrifugal/centrifuge#612).
  • Redis Sentinel: the Sentinel client now periodically refreshes its topology, so changes such as a new master after a failover are picked up more reliably (#1201 and centrifugal/centrifuge#611).
  • Redis Sentinel: Centrifugo also inherited several important Redis Sentinel setup stability improvements from the updated rueidis client (v1.0.77 release notes).

Fixes

  • Fix a possible server process crash (nil pointer panic) that could happen when a delta publication failed to encode to JSON. The broadcast goroutine could panic and terminate the whole node (centrifugal/centrifuge#597).
  • Fix a case where a client could end up with several concurrent connections on the server under Redis load. On disconnect the transport is now closed before the per-channel cleanup, so a slow Redis no longer delays the socket teardown of the old connection (centrifugal/centrifuge#595).
  • Async consumers: do not acknowledge messages that were still being consumed during shutdown, so such messages are re-delivered later instead of being lost (#1196).
  • Logging: raise the internal log handler buffer from 64 to 1024 to reduce the chance of blocking on logging under bursts (#1190).

Miscellaneous

  • This release is built with Go 1.26.6.
  • Dependency updates.
  • We detached App-owned state with stream subscriptions to its own blog post. It was part of PostgreSQL stream broker post before, but the mechanism is generic and not only PostgreSQL specific - so it's better to have it separate.
  • Base Docker image updated to Alpine 3.24 (#1194).
  • See also the corresponding Centrifugo PRO release.

v6.9.1

Choose a tag to compare

@FZambia FZambia released this 13 Jul 06:22
4603be2

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Improvements

  • Possibility to choose color accents in admin web UI.

Fixes

  • Admin web UI: add previously missing API commands to the web UI – map API (map_publish, map_remove, map_read_state, map_read_stream, map_stats, map_clear), shared poll API, etc. – and update the embedded web UI (#1184, commit 3fc933d9).
  • Fix a WARN log about a missing dev key on start – some options and flags left over from the dev page removed in v6.9.0 were not fully cleaned up (#1185, commit 8cee857f).
  • Admin: drop the undocumented and unused fallback that read the admin auth token from a token URL query parameter – the token must be supplied via the Authorization header (#1187, commit bc33546f). Addresses GHSA-v4h4-9j4c-ghgp
  • Removed an unused map ordered option (#1186, commit 8752f242).

Miscellaneous

v6.9.0

Choose a tag to compare

@FZambia FZambia released this 07 Jul 06:43
4015be7

This release comes with ⚠️ BREAKING CHANGES ⚠️

TLDR: Proxy http_headers is now transport-only; Need to configure explicit emulated_headers list for allowed emulated headers in Centrifugo server configuration.

Before v6.9.0, the proxy http_headers option forwarded headers from two different sources:

  • transport-level headers — set on the real connection request (by the client transport or a reverse proxy/gateway in front of Centrifugo);
  • client-supplied emulated headers — sent by the client inside its connect frame via the headers emulation feature.

In v6.9.0 these two sources are split into separate options:

Option Source Trust
http_headers the real connection request only controllable by your edge (a proxy/gateway can set/strip it)
emulated_headers the client's headers emulation map only always client-controlled — always an untrusted input

http_headers no longer forwards emulated headers. To forward a header supplied via headers emulation, you must now list it in the new emulated_headers option near http_headers.

Why we had to make this a breaking change. Before v6.9.0 a name listed in http_headers could be filled from either the real connection request or the client's emulation map. That made a trusted header like x-user-id forgeable in a way that is not the operator's mistake:

  • An operator adds x-user-id to http_headers for a legitimate reason — their reverse proxy sets it, and they want that identity forwarded to the backend. They have no reason to expect this also lets a client supply x-user-id via emulation, especially if they have never heard of the headers emulation feature.
  • That reverse proxy might set x-user-id only for authenticated requests and leave it fully unset otherwise.
  • A client then sends x-user-id in its connect frame via emulation. For any request where the proxy did not set the real header, Centrifugo forwarded the client's forged value to the backend, which trusted it as an authenticated identity.

A setup where the proxy always sets x-user-id (for example to an empty string even for anonymous requests) is not vulnerable. But Centrifugo cannot inspect your proxy to know whether you did that, and cannot tell a genuine x-user-id from a client-emulated one at request time — so there is no way for Centrifugo to make this safe automatically or to warn only the affected setups.

The only robust fix is structural to make operators aware of the feature: split the sources so http_headers is incapable of carrying a client-emulated value. A name in http_headers is now sourced only from the real HTTP connection; anything a client sends via emulation must be explicitly opted into emulated_headers (and is clearly documented as untrusted input). This removes the possibility of the flaw entirely, rather than relying on every operator to configure their proxy defensively against a feature they may not even know exists.

Are you affected? Only if you rely on headers emulation:

  • using headers option in centrifuge-js
  • using headers option in centrifuge-dart (web platform only — on native dart:io these are sent as real WebSocket upgrade headers and are not affected)
  • using headers option in centrifuge-csharp
  • using unidirectional transports and passing headers as part of ConnectRequest

You are not affected if you are not using headers at all or only forward real transport headers (e.g. Cookie, Authorization, X-Real-Ip set by your reverse proxy or by native clients) — those keep working under http_headers with no change.

How to migrate: Before upgrading to v6.9.0, add the header names you allow to be sent over headers emulation to emulated_headers proxy configuration object option near http_headers. Apply this change to every proxy that used emulated headers (connect, refresh, channel proxies, RPC proxies, and any named proxies in the top-level proxies list).

{
  "client": {
    "proxy": {
      "connect": {
        "enabled": true,
        "endpoint": "https://your_backend/centrifugo/connect",
        "http_headers": ["X-User-Id", "Authorization"],
        "emulated_headers": ["Authorization"]
      }
    }
  }
}

If you can't decide which headers to move right away, but need to update to v6.9.0 – then as a workaround, copy the whole http_headers list into emulated_headers nearby to preserve the pre-v6.9.0 behavior, then trim emulated_headers down to only the names your backend treats as untrusted client input.

Long-term, we will also rename headers to emulated_headers in SDKs that provide this feature.

Please reach out in the community rooms if the help with the migration is needed.

The security issue was reported in GHSA-9468-v6mj-fppw.

Improvements

  • NATS JetStream consumer: recreate the consumer on ErrConsumerDeleted, ErrConsumerNotFound and ErrStreamNotFound instead of getting permanently stuck (#1166, commit 920d0c23). By @thuy-le-kafi.
  • Reworked web admin UI — now Vite-based, uses CodeMirror instead of Monaco (for offline work) and includes various UX improvements (#1169, commit fa984f0f).
  • NATS JetStream consumer: back off redelivery with capped exponential delay instead of an instant Nak, avoiding hot redelivery loops on a poison message (#1175, commit ddda397e).
  • Google Pub/Sub consumer: re-subscribe with capped backoff on a receive error instead of exiting the receive loop (which previously left the consumer silently stopped) (#1176, commit 5f6b3871).
  • NATS JetStream consumer: reset the consume backoff only after a session has run healthy long enough, preventing rapid reconnect flapping (#1176, commit c591b954).

Fixes

  • Authentication: hold the read lock across the whole token verification to fix a data race between token verification and JWKS/config reload (#1168, commit e30aca89).
  • PostgreSQL broker: fix hashtext(channel) integer overflow that could panic shard routing when the hash landed exactly on INT_MIN (#1170, commit b52a3cb4).
  • PostgreSQL broker: self-heal a partial fresh install where only one of the JSONB/binary variant tables was created, which previously wedged schema setup (#1171, commit cd85c450).
  • PostgreSQL broker: fix publication timestamps being zeroed by incorrect timestamptz text parsing (#1174, commit 3e163854).
  • PostgreSQL stream broker: fix reverse history pagination returning already-seen or empty pages and never reaching older messages (#1177, commit 2a58bf7f).
  • PostgreSQL outbox: ping the advisory-lock connection while the worker is busy (not only when idle) so a silently dropped lock session is detected promptly, preventing dual-leader processing (#1172, commit aee4cb6c).
  • NATS: strip the internal epoch tag before delivering publications so it no longer leaks to clients (#1174, commit 05fb837c).
  • Azure Service Bus: abandon (instead of complete) a message when processing fails so it is redelivered rather than silently dropped (#1173, commit 0b59fc3a).
  • Azure Service Bus: guard a boolean application-property type assertion against a panic on non-string values (#1172, commit 4cce70ff).
  • Unidirectional WebSocket: clear the HTTP/2 write deadline after a frame ping — a leftover expired deadline could otherwise fail the stream permanently on HTTP/2 ([#1175](https://github.com/centrifu...
Read more

v6.8.4

Choose a tag to compare

@FZambia FZambia released this 30 Jun 04:07
9f72c66

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Fixes

  • Centrifugo now bounds the size of a WebSocket message after permessage-deflate decompression, see #1162. websocket.message_size_limit alone only bounded the compressed bytes received on the wire, so without an additional limit a small compressed frame could be decompressed into a much larger amount of memory (a "decompression bomb" attack). By default, the limit is derived from message_size_limit multiplied by the default multiplier (10); messages exceeding it cause Centrifugo to close the connection with a message too big close code.
    Two new options websocket.decompressed_message_size_limit and uni_websocket.decompressed_message_size_limit allow tuning this limit if needed. Only effective when compression is enabled. Reported by @alanturing881 via GHSA-q6mr-3g59-5m8x.

Miscellaneous

  • New blog post Scaling Redis Pub/Sub to Millions of Channels and Hundreds of Subscriber Nodes which shares the experience of working with Redis Pub/Sub in Centrifugo.
  • PostgreSQL broker metrics were split into per-kind broker_* / map_broker_* subsystems and renamed with a postgres_ prefix to align with the rest of the broker metric conventions, see #1161. Previously stream and map PG brokers shared a pg_broker_* subsystem and were told apart by a broker label, so brokers with the same (or default) name collided. This is a breaking change (but PostgreSQL is still experimental so we decided to change it) for dashboards and alerts in deployments using the PostgreSQL broker – the broker label is now broker_name, and metric names changed as follows: pg_broker_cleanup_rows_deleted_totalbroker_postgres_cleanup_removed_total, pg_broker_outbox_cursor_lag_secondsbroker_postgres_outbox_cursor_lag_seconds / map_broker_postgres_outbox_cursor_lag_seconds, pg_broker_partitionsbroker_postgres_partitions / map_broker_postgres_partitions. See exposed metrics for the full list.
  • This release is built with Go 1.26.4
  • Dependency updates
  • See also the corresponding Centrifugo PRO release.

v6.8.3

Choose a tag to compare

@FZambia FZambia released this 16 Jun 19:51
02cdc96

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Improvements

  • New auto_cache_recover channel namespace option to automatically recover subscriptions on (re)subscribe without the subscriber requesting recovery itself, see #1158. In cache recovery mode this delivers the latest channel publication on every (re)subscribe – without the client providing an empty since position itself. It also enables this for server-side subscriptions, which is especially useful for unidirectional clients that may not even know channel names. The option requires force_recovery and force_recovery_mode set to cache. Subscribe and connect proxies may also enable it per subscription with the new cache_recover field in SubscribeOptions.
  • OpenTelemetry: Centrifugo node ID is now used as the service.instance.id resource attribute, see #1155. Each Centrifugo process now reports telemetry under a distinct identity, which avoids backends that require points of a time series to arrive in order (notably Google Cloud Managed Service for Prometheus) rejecting or collapsing metrics when several instances report under the same identity. OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES still take precedence over Centrifugo defaults.
  • All official Centrifugo SDKs now support a getState subscription callback – read the stream position first, then load your initial state, and return the position so the SDK subscribes from exactly there and recovers on every reconnect. This closes the gap between loading state from your own database and subscribing, see Using recovery in your app.
  • All official Centrifugo SDKs now support publication filtering by tags – clients can subscribe with a filter expression so only publications whose tags match are delivered, reducing bandwidth and client-side processing (previously available in centrifuge-js only).

Documentation

  • The Client protocol chapter was reworked and now ships with diagrams explaining the frame structure, command/reply sequence, push delivery, ping-pong, batching, and the JSON/Protobuf formats.
  • The History and recovery chapter was significantly expanded with diagrams covering stream vs cache recovery modes, the recovery decision flow, and recovery storm mitigation.
  • The GrandChat tutorial was actualized for 2026 – the Django/React code was modernized to recent versions and made more idiomatic and type-safe, and a new Two-column layout chapter shows how to build a Telegram/Slack-style messenger layout (room list and open room side by side) live from a single personal-channel subscription.

Miscellaneous

  • The linux/386 (32-bit x86) binary is no longer published in releases, see #1154.
  • This release is built with Go 1.26.4
  • Dependency updates
  • See also the corresponding Centrifugo PRO release.

v6.8.2

Choose a tag to compare

@FZambia FZambia released this 08 Jun 18:10
29ff48f

Centrifugo is an open-source scalable real-time messaging server. It instantly delivers messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE), GRPC, WebTransport). Centrifugo is built around channel subscriptions – so it's a user-facing PUB/SUB server.

Centrifugo is language-agnostic and can be used to build chat apps, live comments, multiplayer games, real-time data visualizations, collaborative tools, AI streaming responses, etc. in combination with any backend. It is well suited for modern architectures and allows decoupling the business logic from the real-time transport layer.

Official client SDKs are available for JavaScript (browser, Node.js, React Native), Dart/Flutter, Swift, Java, Python, Go, and .NET. In addition, Centrifugo supports a unidirectional approach for simple use cases with no SDK dependency.

For details, go to the Centrifugo documentation site. For runnable demos see centrifugal/examples.

What's changed

Improvements

  • OpenTelemetry: authenticate the OTLP exporter with Google Cloud Application Default Credentials (ADC) via the new google_cloud_adc_auth option, see #1143 and #1148. This allows exporting traces directly to Google Cloud's OTLP endpoint (telemetry.googleapis.com) without a sidecar collector, and works with both the grpc and http/protobuf exporter protocols.
  • Kafka consumer: added a configurable dial_timeout (default 3s) for establishing a TCP connection to a single broker, and made the initial Ping timeout scale with the number of seed brokers so discovery no longer fails prematurely when some brokers are unreachable, see #1151.
  • Centrifugo official Helm chart now supports k8s Gateway API - see Helm chart 13.3.0 release
  • Centrifugo now does not embed generated JSON config schema - configuration structure for configdoc is calculated in runtime, #1153

Fixes

  • Kafka consumer with AWS MSK IAM auth: re-assume the STS role on each SASL re-auth instead of reusing cached credentials, fixing periodic ILLEGAL_SASL_STATE errors during re-authentication, see #1146 by @samir-is-here which fixes #1144.
  • Fix unidirectional subscribe stream proxy not closing on unsubscribe, see #1150.

Miscellaneous

  • This release is built with Go 1.26.4
  • Dependency updates
  • This is the latest release that ships linux/386 binary
  • See also the corresponding Centrifugo PRO release.