gem version

Tuning for Server Sent Events and WebSockets

Relevant selection for this article:

Nginx

Using SSE with WebSockets generally means that an application must handle multiple concurrent connections. Ruby applications usually can't do this and need a special configuration tweak.

Ruby concurrency tweak

Passenger's highly optimized load balancer assumes that Ruby apps can handle 1 (or thread-limited amount of) concurrent connection(s). This is usually the case and results in optimal load-balancing. But endpoints that deal with SSE/Websockets can handle many more concurrent connections, so the assumption leads to degraded performance.

You can use the force max concurrent requests per process configuration option to override this. The example below shows how to set the concurrency to unlimited for /special_websocket_endpoint:

server {
   listen 80;
   server_name www.example.com;
   root /webapps/my_app/public;
   passenger_enabled on;

   # Use default concurrency for the app. But for the endpoint
   # /special_websocket_endpoint, force a different concurrency.
   location /special_websocket_endpoint {
       passenger_app_group_name foo_websocket;
       passenger_force_max_concurrent_requests_per_process 0;
   }
}
In Passenger 5.0.21 and below the option above was not available yet. In those versions there is a workaround for Ruby apps. Enter code below into config.ru to set the concurrency (on the entire app).
if defined?(PhusionPassenger)
  PhusionPassenger.advertised_concurrency_level = 0
end

Action Cable integration

Are you using Ruby on Rails with Action Cable? Please refer to our Action Cable integration guide.

Demo apps

You can find the Passenger SSE demo app here and the WebSocket demo app here.

light mode dark mode
Passenger 6 Passenger 6