PHP-native Real-time Backend
A Socket.IO alternative that runs on plain PHP + MySQL — authoritative shared state, delta sync and presence with no Node process or WebSocket daemon.
This is a PHP-native replacement for a Node.js/Socket.IO real-time layer. It gives you shared authoritative state, event fan-out, presence and live viewer counts, roles and permissions — all delivered over ordinary HTTP on standard PHP + MySQL hosting, with no persistent Node process and no WebSocket daemon. I built it to retire the Socket.IO VPS behind TuneVote, but the module is app-agnostic and reusable.
Why build this at all#
Socket.IO is lovely until you have to host it. A WebSocket daemon needs a
long-lived process, which rules out most shared and cPanel-style hosting and
turns into a VPS you have to babysit. The interesting constraint here was: can I
get the same developer experience — socket.on(...) / socket.emit(...) — on
nothing but PHP-FPM and a MySQL database? Migration is deliberately mechanical:
socket.on becomes client.on, socket.emit becomes client.emit, and rooms
become sessions.
The core#
Each session owns one authoritative JSON snapshot plus a monotonic version and
an append-only event log. Late joiners get the snapshot; everyone else pulls
deltas. The part I care most about is correctness under concurrency: every
mutation is serialised per session with a GET_LOCK + SELECT … FOR UPDATE and
an optimistic version check, so there are no lost updates even when two writers
race. Clients keep a since cursor and receive events over SSE, long-poll
(holding the request up to ~25 s) or short-poll fallback; if a client falls
behind the retained window, it gets a fresh snapshot to resync instead of a
broken stream.
Architecture#
The module is PSR-4 (Realtime\) and cleanly layered: an HTTP kernel with CORS,
a session service, an action registry with server-side permissions, transports
(long-poll and SSE) and a pluggable storage driver — MySQL by default, Redis as
an optional scale-out path behind the same interface. Presence is heartbeat +
TTL, counted on read. Auth is server-authoritative with HMAC-signed tokens, plus
rate limiting. The JS client handles the transport negotiation, reconnects and
snapshot-on-gap resync so callers just subscribe to events. It ships with
integration tests covering sync, presence and rate limiting.
Next, have a look at
Weft
A local-first, self-hostable Notion alternative — nested-page block editor, real-time co-editing over Yjs, Git-style version history and a graph view, all in one command.
PDFChef
A local-first, in-browser document workspace where you drag individual pages across sources into entirely new documents — and export, with no round-trips to a server.