What is the right way to broadcast a message with PubSub and receive with Channel

I have an Elixir 1.54 and Phoenix umbrella app containing:

The [AdminWeb] calls a function defined in [Admin] that pulls information from a
Database, then converts it to a list of maps and should broadcast it to DisplayWeb channel:

[AdminWeb] --> [Admin] --> [DisplayWeb]

The code in [Admin] looks like this:

# news.ex

    def news_sort(id_list) do
        news_payload = news_items_from_db() |> struct_to_map()
        PubSub.broadcast(Admin.PubSub, "cast:news", news_payload)

The code in [DisplayWeb] looks like this:


  def join("cast:news", _payload, socket) do
    self() |> send({:after_join, "cast:news"})

 def handle_info({:after_join, "cast:news"}, socket) do
    broadcast!(socket, "newscast", %{data: news_payload})
   {:noreply, socket}

The PubSub.broadcast in [Admin] returns :ok message but the [DisplayWeb] does not receive any message. It neither works not returns any error message.

Please, what’s wrong with the code? What’s the right way to implement this solution?

you forgot to subscribe the message.


You must use Endpoint.broadcast/3 instead. Where Endpoint in this case is your application’s endpoint.

If you have a look on the source code for this broadcast/3 function I mentioned, you’ll notice it ends up calling PubSub.broadcast/4 too. But the catch here is that it is broadcasting a %Phoenix.Socket.Broadcast{} struct instead of plain data like you are doing. And this struct is most likely the language phoenix channels speak internally. Which, in other words, means that you are broadcasting a message that channels cannot understand. And so this explains why your clients receive no message.

1 Like

@derek-zhou, @satom99, thanks for your response. I’ve been advised to use PG2 since AdminWeb/Admin and DisplayWeb runs on two separate servers(4001, 4002). I’m currently researching how to use it properly.