It depends mostly on the direction of the data flow:
1. If updates only flow one way (server → client), like order status changes or new records appearing, Server-Sent Events (SSE) are usually enough and simpler than WebSockets. SSE runs over plain HTTP, auto-reconnects natively in the browser, and works through most proxies/load balancers without special config.
2. If you need two-way communication (chat, live cursors, collaborative editing, anything the client also needs to push), go with WebSockets. Don't reach for WebSockets just because it feels more "real-time" — it adds real complexity you don't need if the app is really just server-to-client notifications.
3. Skip polling once you're past a small user base. Even long-interval polling adds up fast and wastes server resources compared to either SSE or WebSockets holding a single open connection.
4. Reconnects: SSE handles this automatically (the browser reconnects and sends a Last-Event-ID header so you can resume from where it left off). For WebSockets, you have to build this yourself — exponential backoff on the client, and a way to resync state after a dropped connection (usually a "fetch latest state" REST call on reconnect, since you can't trust that you didn't miss messages while disconnected).
5. Authentication: for WebSockets, authenticate during the initial handshake (token in the connection URL or an initial auth message), not per-message. For SSE, the connection is just an HTTP request, so normal auth headers/cookies work fine.
6. Scalability: the real challenge isn't the protocol, it's fanning out messages across multiple server instances. You'll need a pub/sub layer (Redis Pub/Sub, or a managed service like Ably/Pusher) so that when instance A gets an update, it can notify clients connected to instances B and C. Sticky sessions or a shared connection registry are also needed since WebSocket/SSE connections are stateful per server.
In production, a common pattern is: SSE (or a managed real-time service) for simple one-way updates, WebSockets reserved for genuinely bidirectional features, and Redis pub/sub tying it together once you have more than one server instance.