How to architect a collaborative web application for live updates?

When using collaborative applications like issue trackers, planning tools, etc. it can be very frustrating to have to keep hitting refresh to make sure you’re viewing the same state as your colleagues. Therefore I want to build my applications so that when one user changes something, it shows up on everyone’s screens. But I struggle to find good architectural discussions beyond "use polling" or "use web sockets".

I can imagine a few ways of doing it:

  1. Use event sourcing throughout the application. User actions are sent as commands to the server and the server responds with events. The client maintains its own projection.

    Pros: Only one round trip of latency. All the benefits of CQRS.

    Cons: Complex logic for maintaining consistency, fetching snapshots, etc., both on the server and the client. While conceptually simple, event sourcing can be quite complex, especially for ad-hoc implementations.

  2. A conventional server, but update notifications are sent to the client on a side channel. The client is then responsible for fetching the new data. A way of implementing this would be to build a conventional RESTful HTTP interface, but every time a PUT, POST or DELETE is made, clients receive the URL of the resource that changed, make another GET to it.

    Pros: Apart from the notification channel, it’s a mature design pattern as old as the web itself, supported by frameworks, relational databases, etc. and easy for everyone to grok.

    Cons: Double round trip latency. Needs a message queue or something if multiple back-end instances are used.

  3. When objects change, push entire new copies to the client. Instead of one-shot fetching, clients subscribe to resources. The server can be implemented according to either of the above strategies, with the associated pros and cons.

    Pros: One round trip latency. Very simple client.

    Cons: Could be wasteful to send a lot of big objects that the client might not even need.