Centrifugo is an open-source scalable real-time messaging server. Centrifugo can instantly deliver messages to application online users connected over supported transports (WebSocket, HTTP-streaming, Server-Sent Events (SSE/EventSource), GRPC, WebTransport). Centrifugo has the concept of a channel – so it's a user-facing PUB/SUB server.
For details, go to the Centrifugo documentation site.
What's changed
This release introduces two new subscription primitives and three Postgres-backed components. Centrifugo evolves from a channel-based pub/sub server into a real-time companion for Postgres-backed applications. From a stream based broker to a state synchronization realtime backend.
A blog series accompanies this release. Two posts are published today:
- Shared poll subscriptions: O(unique items) polling with low-latency updates introduces one of the new subscription types,
- Recreating a Two Million Particle World at 30 Hz with Centrifugo puts shared poll to work reproducing David Gerrells' particle simulation on top of Centrifugo's WebSocket protocol.
Five more posts will follow during this week, covering map subscriptions, the PostgreSQL stream broker, the PostgreSQL controller, and a wrap-up tying it all together:
- Day 2: Map subscriptions (Part 1) — synchronized key-value state and presence
- Day 3: Map subscriptions (Part 2) — when your PostgreSQL transaction is your real-time publish
- Day 4: Transactional publishing for stream subscriptions with PostgreSQL
- Day 5: Multi-node Centrifugo on PostgreSQL alone
- Day 6: Wrap-up: Beyond PUB/SUB: new foundations, and a real-time companion for PostgreSQL
Note, we consider map subscriptions and shared poll experimental for now. Features are huge and we expect API to stabilize within next months.
Highlights of release
- Map subscriptions — new subscription type for synchronized key-value collections (cursors, presence, scoreboards, dashboards, feature flags).
- Shared poll subscriptions — new subscription type for read-only state where the backend doesn't control writes (third-party feeds, configuration sync, live counters).
- PostgreSQL stream broker — transactional publishing for stream subscriptions inside your SQL transactions.
- PostgreSQL map broker — transactional publishing for map subscriptions inside your SQL transactions.
- PostgreSQL controller — multi-node Centrifugo clusters on PostgreSQL alone, no Redis required.
Yes, Centrifugo multi-node cluster only on PostgreSQL is now possible.
Map subscriptions
A new subscription type that delivers synchronized key-value collections over the same WebSocket connection. Centrifugo keeps the collection in the map broker; the client stays in sync.
Three modes for different state shape:
ephemeral— usually memory or Redis backed, no recovery on reconnect (cursors, typing indicators, in-flight game state).recoverable— time-bounded recovery from stream within a window, state converges with the help of offset/epoch mechanics.persistent— durable, no per-key TTL — entries live until explicitly removed (feature flags, configuration, catalog state).
Key features:
- Three-phase sync protocol resolves the race between paginated initial state and concurrent updates.
- Per-key TTL handles cleanup on disconnect.
- CAS-style conditional writes handle concurrent updates safely.
- Convergence on reconnect guaranteed by offset/epoch tracking (in recoverable and persistent modes).
Docs: Map subscriptions
Demos: v6/map_demo collection — cursors, polls, sprint board, scoreboard, inventory, lobby, tickers, sync protocol visualizer.
Map presence
Map subscriptions introduce a new presence model built on the same sync protocol. Two server-managed subscription types replace the polling-style traditional presence API for use cases that need it:
map_clients— one entry per connection (client presence).map_users— one entry per user (user presence).
Enabled via map_clients_presence_channel_prefix and map_users_presence_channel_prefix on the parent namespace. Presence is published to a separate channel (prefix + channel), so subscribers opt in independently of the parent subscription. Works alongside any parent subscription type (stream, map, shared_poll).
Advantages over traditional presence:
- Paginated state delivery for large participant lists.
- Stream-based catch-up on reconnect (with
recoverablemode) — clients receive only the join/leave changes they missed, no full re-fetch. - Out of the box convergence (must be in recoverable mode for convergence property)
Docs: Presence channels
Demo: v6/map_presence_demo — 100k and 1M presence members synchronized to a single browser tab
Shared poll subscriptions
Server-side polling inversion for read-only state where the backend doesn't control writes. Instead of N clients each polling the backend, Centrifugo aggregates interest across all clients on a node and polls the backend once per cycle for the union of tracked keys. Backend load scales with O(unique items tracked), not O(connected clients).
Key features:
- Per-key authorization via HMAC signatures (faster than JWT, first-class values in protocol).
- Direct publish via
shared_poll_publishlowers latency on application write paths. - Versionless and versioned modes for flexible backend integration.
- Cold-key auto-poll: when a new client tracks a key with no cached data, Centrifugo triggers an immediate backend poll without waiting for the next cycle.
- Reconnect resilience with version comparison: clients reconnect, replay tracked keys, only changed data re-delivered.
Docs: Shared poll
Blog: Shared poll subscriptions: O(unique items) polling with low-latency updates
Demos: v6/shared_poll_demo — votes, drones
PostgreSQL stream broker
Transactional publishing for stream subscriptions. The cf_stream_publish SQL function commits inside your application's SQL transaction — your INSERT/UPDATE and the real-time publish commit together. If the transaction rolls back, the real-time update never happened. No application-side outbox to maintain, no CDC pipeline.
Architecture:
- Partitioned outbox table (
cf_stream) with daily date ranges. - LISTEN/NOTIFY for low-latency wakeup, polling for correctness.
- Drop-partition cleanup — vacuum-free at scale.
- Two independent TTLs:
HistoryTTL(queryable history) andHistoryMetaTTL(channel epoch). HistorySizeenforced at read time, not write time.
Pairs with the SDK's getState callback for the app-owned state pattern: clients load initial state from your application API, then subscribe from the captured stream position. The SDK switches paths automatically — replays from stream history on normal reconnects, calls getState only when the gap exceeds what history covers.
Docs: Engines — PostgreSQL Broker
Example: v6/pg_stream_broker — kitchen orders, multi-tenant per-restaurant channels
PostgreSQL map broker
Transactional publishing for map subscriptions. The cf_map_publish and cf_map_remove SQL functions commit inside your application's SQL transaction — write your row, publish the map update, both atomic.
Same outbox-on-Postgres foundation as the stream broker — partitioned outbox table, LISTEN/NOTIFY wakeup, daily partition retention, vacuum-free cleanup.
The map broker stores cf_map_state and cf_map_stream in your PostgreSQL database. The state lives in cf_map_* tables that Centrifugo owns, queryable from psql. Best fit when Centrifugo is the natural store for the data — feature flags, IoT device fleet telemetry, lobby rosters, collaborative cursors.
Docs: Map subscriptions — PostgreSQL
PostgreSQL controller
The control-message bus for multi-node Centrifugo (subscribe propagation, disconnects, presence pings, surveys) can now run on PostgreSQL — the same outbox-on-Postgres foundation as the brokers. Until this release, multi-node OSS Centrifugo required Redis for that bus.
With the stream broker, map broker, and controller all on PG, an OSS cluster runs with PostgreSQL as the only messaging-plane dependency. No Redis, no NATS, no separate pub/sub broker.
For applications already running Postgres for everything else, the messaging plane has what it needs.
Docs: PostgreSQL controller
Other improvements
- PostgreSQL async consumer configuration polish (TLS config, separate notify DSN).
- Schema regeneration and configuration defaults reviewed.
SDK support
Map subscriptions and shared poll subscriptions are currently supported on the client side only by centrifuge-js. Other SDKs continue to support stream subscriptions as before.
Migration notes
The new features are all opt-in:
- Map subscriptions activate when you set
subscription_type: "map"on a namespace. - Shared poll subscriptions activate when you set
subscription_type: "shared_poll"on a namespace. - PostgreSQL brokers/controller activate when you set
broker.type: "postgres",map_broker.type: "postgres", orcontroller.type: "postgres".
Resources
- Documentation home
- Map subscriptions docs
- Shared poll docs
- PostgreSQL stream broker docs
- PostgreSQL map broker docs
- Engines docs (Memory, Redis, PostgreSQL)
- Examples — v6/map_demo, v6/map_presence_demo, v6/shared_poll_demo, v6/pg_stream_broker
Miscellaneous
- This release is built with Go 1.26.3
- Dependency updates
- See also the corresponding Centrifugo PRO release.