FeathersJS Real-time Event Broadcasting in Serverless Deployments
0 reputation · 02 May 2021, 21:53 UTC
0 reputation · 02 May 2021, 21:53 UTC
Reducing operational costs for low-traffic workloads often involves transitioning from persistent servers to serverless architectures. While FeathersJS supports this decoupling, the stateless nature of serverless functions creates a conflict with the framework's real-time capabilities.
In a standard deployment, Socket.io manages persistent connections to broadcast events. However, when scaling horizontally across isolated serverless instances, these instances cannot natively communicate to synchronize event emissions to clients connected to different nodes.
The documented solution involves integrating a centralized Redis adapter to bridge these instances. There is uncertainty regarding the efficiency of this pattern for extremely low-traffic environments where the cost of maintaining a Redis instance might offset the savings gained from serverless compute.
35775 reputation · 03 May 2021, 03:05 UTC
In a serverless deployment, the Redis adapter ensures that an event emitted by one isolated function instance is broadcast to all other active instances. However, it does not provide a persistent state for clients or event history.
The Redis adapter maintains consistent delivery across cold starts, but not continuity. When a serverless instance cold-starts, it establishes a new connection to the Redis pub/sub channel. Any event emitted while that specific instance was inactive is lost to that instance; the adapter does not "replay" missed events to newly spawned functions.
Furthermore, because serverless functions are stateless, the WebSocket connection itself is typically managed by a gateway (like AWS API Gateway WebSocket API) or a separate proxy. The Redis adapter simply tells the current function instance to push a message to the gateway for a specific client ID.
There are no built-in FeathersJS mechanisms for cross-instance broadcasting that avoid an external dependency. Because serverless instances share no memory or network socket, a "third party" must act as the message bus. If a persistent Redis instance is cost-prohibitive, consider these alternatives:
To verify the behavior of your current setup, you can simulate a distributed environment locally:
Diagnostic Detail Needed: Which serverless provider and WebSocket gateway are you using? The recommendation changes significantly if you are using a managed gateway (like AWS) versus a containerized serverless approach (like Google Cloud Run).
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 03 May 2021, 07:24 UTC
While the Redis adapter solves the cross-instance broadcasting problem, it is important to clarify the transport-level requirement for sticky sessions. In a standard FeathersJS setup using Socket.io, the initial HTTP handshake must be routed to the same serverless instance for the duration of the upgrade to WebSockets.
In a pure serverless environment, this often necessitates a specific infrastructure configuration:
transports: ['websocket'] in the client configuration bypasses the HTTP polling phase, avoiding the handshake mismatch entirely.Without one of these configurations, clients may experience intermittent connection failures regardless of whether a Redis adapter is present to handle the subsequent event broadcasting.