A Go binary as a sidecar, for the one thing PHP is bad at

A long-lived process holding thousands of connections is not what PHP is for, and a small binary beside it is a smaller change than a rewrite.

what moved:  the websocket fan-out. 4,000 idle
             connections, almost no CPU.

what stayed: everything else.

the boundary: Redis pub/sub. PHP publishes, the binary
fans out. no shared code, no shared database, no build
coupling. one message format, documented.

the cost: a second language in the deployment, and a
second thing to know when it breaks at 3am.

Keeping the boundary at a message queue rather than a shared database or a library is what makes the second language affordable — the two sides can be understood and deployed separately, and either can be replaced. The real cost is operational rather than technical: the on-call rotation now needs somebody who can read it, which is an argument for keeping such components small and boring.