Skip to main content

Server-side subscriptions

Centrifugo clients can initiate a subscription to a channel by calling the subscribe method of client API. We call it client-side subscriptions. In most cases, client-side subscriptions is a flexible and recommended approach to subscribe to channels. A frontend usually knows which channels it needs to consume at a concrete moment.

But in some situations, all you need is to subscribe your connections to several channels on a server-side at the moment of connection establishment. So client effectively starts receiving publications from those channels without calling the subscribe API at all. Centrifugo allows doing this with its server-side subscriptions feature.

It's possible to set a list of channels for a connection in several ways:

  • over connection JWT using channels claim, which is an array of strings
  • over connect proxy returning channels field in result (also an array of strings)
  • providing channels as part of unidirectional transport connect payload – if client has enough permissions subscriptions will be created
  • dynamically over server subscribe API

On the client-side, when using bidirectional transport and our SDKs you need to listen for publications from server-side channels using a top-level client event handler. For example with centrifuge-js:

const centrifuge = new Centrifuge(address);

centrifuge.on('publication', function(ctx) {
const channel = ctx.channel;
const payload = JSON.stringify(ctx.data);
console.log('Publication from server-side channel', channel, payload);
});

centrifuge.connect();

I.e. listen for publications without any usage of subscription objects. You can get a channel publication relates to by using field in the callback context as shown in the example above.

tip

The same best practices of working with channels and client-side subscriptions equally applicable to server-side subscription.

Dynamic server-side subscriptions

See subscribe and unsubscribe server API

Automatic personal channel subscription

It's possible to automatically subscribe a user to a personal server-side channel.

To enable this you need to enable the user_subscribe_to_personal boolean option (by default false). As soon as you do this every connection with a non-empty user ID will be automatically subscribed to a personal user-limited channel. Anonymous users with empty user IDs won't be subscribed to any channel.

For example, if you set this option and the user with ID 87334 connects to Centrifugo it will be automatically subscribed to channel #87334 and you can process personal publications on the client-side in the same way as shown above.

As you can see by default generated personal channel name belongs to the default namespace (i.e. no explicit namespace used). To set custom namespace name use user_personal_channel_namespace option (string, default "") – i.e. the name of namespace from configured configuration namespaces array. In this case, if you set user_personal_channel_namespace to personal for example – then the automatically generated personal channel will be personal:#87334 – user will be automatically subscribed to it on connect and you can use this channel name to publish personal notifications to the online user.

Maintain single user connection

Usage of personal channel subscription also opens a road to enable one more feature: maintaining only a single connection for each user globally around all Centrifugo nodes.

user_personal_single_connection boolean option (default false) turns on a mode in which Centrifugo will try to maintain only a single connection for each user at the same moment. As soon as the user establishes a connection other connections from the same user will be closed with connection limit reason (client won't try to automatically reconnect).

This feature works with a help of presence information inside a personal channel. So presence should be turned on in a personal channel.

Example config:

config.json
{
"user_subscribe_to_personal": true,
"user_personal_single_connection": true,
"user_personal_channel_namespace": "personal",
"namespaces": [
{
"name": "personal",
"presence": true
}
]
}
note

Centrifugo can't guarantee that other user connections will be closed – since Disconnect messages are distributed around Centrifugo nodes with at most once guarantee. So don't add critical business logic based on this feature to your application. Though this should work just fine most of the time if the connection between the Centrifugo node and PUB/SUB broker is OK.