gem version

Tuning for Server Sent Events and WebSockets

Relevant selection for this article:

Nginx
Although Passenger supports Server Sent Events (SSE) out of the box, the Apache integration mode has issues with Apache. We recommend using either Passenger Standalone with Apache as a reverse proxy, or Passenger with the Nginx integration mode.

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:

<VirtualHost *:80>
    ServerName www.example.com
    DocumentRoot /webapps/my_app/public

    # Use default concurrency for the app. But for the endpoint
    # /special_websocket_endpoint, force a different concurrency.
    <Location /special_websocket_endpoint>
       PassengerAppGroupName foo_websocket
       PassengerForceMaxConcurrentRequestsPerProcess 0
    </Location>
</VirtualHost>
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