Are sticky or affinity sessions needed when deploying Phoenix?

Hi! We’re currently deployed on AWS ECS with an ALB load balancer with sticky sessions enabled. We’re looking at deploying elsewhere and I’m curious if we still need sticky or affinity sessions.

We store quite a bit of state in the channel. The client tells the server which models/queries it wants to subscribe to and and the channel on the server uses Endpoint.subscribe to subscribe. Here’s an example (simplified)

defmodule WebApp.SessionChannel do
  def handle_in("subscribe", model_uuid, socket) do
    WebApp.Endpoint.subscribe("model:" <> model_uuid)

When changes come in, the server broadcasts those changes using Endpoint.broadcast! to any connected clients. E.g.

  def handle_in("mutation", %{id => model_uuid, mutation => mutation}, socket) do
    WebApp.Endpoint.broadcast!("model:" <> model_uuid, "update", mutation)

And, lastly, the channel pushes any updates for subscribed topics to the client:

  def handle_info(%Broadcast{topic: "model:" <> _id, event: "update", payload: mutation}, socket) do
    push(socket, "model-update", mutation)

My understanding is we need the channel to the be alive for the subscriptions to stay alive and we need the client connecting to the same server to keep the channel alive. Thus, we need sticky sessions.

Is that accurate?

Only if your channel connection is using longpoll. The websocket connection is stateful and long running, so there’s no time when the connection would be able to switch to a different server.

Thanks so much! About 10% of our users are using Longpolling due to the network policies of the school networks.

What would be the alternative? Giving each browser tab a session ID and then creating a genserver for each session ID which would store all the subscriptions?

If your nodes are clustered everything should work just fine, but state will be transfered between nodes if needed.

@LostKobrakai I’m a bit confused. You wrote,

Only if your channel connection is using longpoll.
Which makes me think we need sticky sessions for long polling. But then you wrote:

If your nodes are clustered everything should work just fine

Could you explain? Do you mean the GenServer approach would work fine?

1 Like

You want to have sticky sessions with long polling powering channels, because that will prevent the communication overhead of moving channel state between nodes. But you don’t need sticky sessions for it to work at all.

1 Like