So, I needed to push some data from the server. Oh look, this "EventSource" thing looks perfect. Made for exactly this, and seems much easier to set up than websockets.
I implement, test things locally. Everything seems to work well. Push to production.
Can you guess what the problem is? Maybe reading some documentation will help?
Just kidding, it's not in there (as of 2018-02-17). (There is a note in the spec though.)
Turns out, EventSource connections count as normal http connections, which are capped at 6 per domain in chrome and firefox, and they stay open as long as the tab is open. If a user opens multiple tabs, each new tab of the site is slower to load. After several tabs, the domain becomes completely unresponsive. New tabs fail to load and ajax stops working in existing tabs.
There are some hacky workarounds, but they complicate things significantly. One idea is to use LocalStorage for communication between tabs, and make sure only one master tab uses EventSource.
Another is to have different domain(s) handle the connection. In my case, this involved changing dns, a few changes to nginx configuration, extending the ssl certificate (thank you, LetsEncrypt, for making this easier), setting up CORS, and tweaking the login system a bit to make authentication work across subdomains.
The result is not too terrible, but next time I need server push, I'll go with websockets.