How do Phoenix channels work?

I’m currently designing the architecture for a simple application, in which I will need real time communication. My current plan is to represent each active user as a GenServer on the backend, with a channel connection to each user. Since I want to communicate with each user directly, I think I need a channel with the username (or similar) as the topic.
But I am not sure how channels work and I’m trying to keep the application as memory efficent as possible. I tried reading the Phoenix PubSub source code, but couldn’t get that much out of it. My main question is, whether Phoenix itself uses a GenServer for the channel or if it is just a ETS value. And if Phoenix does use a GenServer per channel, can I acess that GenServer, register it, and or use my own version (PubSub Adapter)?
If none of that is possible I would be interested in knowing how much work it is, implementing something similar to Phoenix channels from cowboy sockets.

Indeed, each channel is a Genserver. Specifically though it’s worth distinguishing between a topic and a channel. If users A, B, and C each subscribe to a topic “room:1” this will create 3 channel genservers, one for each user. If some user D broadcasts a value to topic "room:1" then the 3 genservers will each get a message and will process them concurrently. Each channel can also manually subscribe to additional topics, and receive messages for values broadcasted to those topics.

The registry of which channel processes are subscribed to which topics is held in :ets.


By default it uses pg2, but You can switch to another PubSub if You wish… like Redis for example.

I usually set a user channel, something like “user:#{}”, this way it’s possible to reach anybody by it’s id.

I would recommend this book, because it’s about the subject You are interested in…

1 Like

So could I theoretically write my own PubSub that uses the already spawned GenServers for each user, insead of spawning new ones?
Are there any guides on how to write one or a simple example?

Can you expand on your use case? In general a pubsub doesn’t really need to spawn any per user processes. Performant pubsubs need a subscribers list for sure in something like ets, or redis, but then you just send a message to each subscriber. That send doesn’t require you to have any genservers, nor does it even require that the recipient is a genserver.

What properties of a pubsub do you need that aren’t provided by PhoenixPubsub? Do note that it can be used directly and not just via channels.