Meetflow: The WebRTC Stack That Treats Disconnection Like a First-Class State
A deep look at a self-hosted video platform that combines mediasoup, Socket.io, Redis, and PostgreSQL to keep rooms alive, hosts in control, and speakers visible.
- Meetflow is not just a WebRTC app. It is a state machine for real-time rooms that can survive interruption without losing the room's shape.
- Its most distinctive move is the 30-second grace period, which turns disconnection into a recoverable event instead of an immediate teardown.
- The repo splits cold, warm, and hot state across PostgreSQL, Redis, and in-memory mediasoup objects so each layer handles the kind of data it is best suited for.
- Host controls and active-speaker detection are handled server-side, which makes the product feel like a managed meeting system rather than a signaling demo.
The 30-Second Ghost That Makes Meetflow Feel Real
The sharpest idea in Meetflow is also the quietest one. When a participant disconnects, the room does not instantly forget them. The system keeps that user in limbo long enough to reconnect, then cleans up only if they fail to return.
That is a product decision, not just an implementation detail. It protects the conversation from network noise, browser hiccups, and brief tab switches, which is where many real-time apps feel brittle.
What Meetflow Actually Is
Meetflow is a self-hosted video conferencing platform built as a monorepo. The backend is a Node.js and Express service, the frontend is a React app, and the media plane is powered by mediasoup, which means the server forwards media instead of asking every client to talk directly to every other client.
| Layer | Role in Meetflow | Why it matters |
|---|---|---|
| Frontend | React SPA for the room UI | Keeps the user experience separate from the media machinery |
| Signaling | Socket.io event bridge | Moves room state and control messages between clients and server |
| Media | mediasoup SFU | Handles multi-party audio and video routing without P2P fan-out |
| Persistence | PostgreSQL and Redis | Stores durable records and live room state in the right places |
That split matters because conferencing is not one problem. Rendering the UI, negotiating sockets, routing media, and remembering who is in the room all fail in different ways. Meetflow keeps those concerns apart instead of flattening them into one pile of event handlers.
Why the Stack Is Split the Way It Is
The backend is organized around domains, not around one giant WebRTC file. Mediasoup owns transport and routing. Socket.io owns signaling and broadcasts. Module code handles meeting and authentication rules. That shape is the first clue that the repo is trying to behave like a product system, not a tutorial.
This separation is especially clean in the media pipeline. A low-level media worker can detect audio activity, then hand that signal off to a custom event bridge, and only then does the room UI react. That avoids the usual trap where the media layer and the interface become tangled in the same callback soup.
mediasoup Is the Real Engine Room
Meetflow uses mediasoup as an SFU, or Selective Forwarding Unit. In plain terms, the server does not mix everyone's media into one giant stream. It receives streams from clients, decides what each participant should get, and forwards them efficiently.
The repo also scales workers across CPU cores. That is a practical move, because media routing is not cheap. Spreading workers across hardware keeps the server from turning into a single point of pressure as the room fills up.
// Conceptual shape of the mediasoup layer
const workers = Array.from({ length: os.cpus().length }, async () => {
return await mediasoup.createWorker();
});
// Routers, transports, and observers are then attached per room
// so the media plane stays isolated from signaling and persistence.
The Clean Trick Behind Active Speaker
The most elegant mechanism in the repo is the active-speaker path. mediasoup's audio-level observer detects who is speaking, and the event is then relayed through the app's signaling layer so the room can mark the right participant as active.
That sounds small until you compare it to the alternative. In a sloppier stack, the media worker would know too much about the UI, or the UI would poll for state and guess. Meetflow avoids both problems by making the media event explicit and the product response downstream.
Host Controls Turn a Call Into a Managed Room
Meetflow includes host controls like kick, lock, and force mute. These are not just interface buttons. The server enforces them, which matters because governance should survive a flaky client or a tampered browser session.
Force mute is the clearest example. The server pauses the producer and emits a signal so the client updates its interface. That keeps the control plane authoritative and the user experience coherent at the same time.
| Control | What it changes | Why server-side enforcement matters |
|---|---|---|
| Lock meeting | Blocks new joins | Prevents UI-only bypasses |
| Kick user | Removes a participant from the room | The room state stays consistent across clients |
| Force mute | Pauses a producer and updates the client | The media plane and the interface agree on the result |
The State Model: Cold, Warm, and Hot
Meetflow's architecture becomes easier to understand if you think in temperature tiers. PostgreSQL holds cold, durable records. Redis holds warm, active room metadata. In-memory mediasoup objects hold the hot stuff, the live WebRTC resources that cannot be serialized away without breaking the call.
That is a sensible split. Database rows are for history and identity. Redis is for sessions and ephemeral coordination. In-memory objects are for the live transport graph that only exists while the room is breathing.
| State layer | Examples | Why it lives there |
|---|---|---|
| PostgreSQL | Users, meetings, reconnect deadlines | Needs durability and auditability |
| Redis | Active room state, locks, transient metadata | Needs fast reads and short-lived coordination |
| In-memory mediasoup state | Routers, transports, producers | Represents live media objects that cannot be stored as plain records |
Meetflow vs the Usual WebRTC Stack
The contrast is easiest to see against the familiar alternatives. A basic peer-to-peer WebRTC app can be simple, but it gets fragile as rooms grow. A tutorial-grade signaling app can look complete, but it often stops at connection setup and never learns how to govern a room.
| Capability | Basic P2P WebRTC | Tutorial signaling app | Meetflow |
|---|---|---|---|
| Multi-party scaling | Poor | Limited | Built around SFU forwarding |
| Reconnect behavior | Usually brittle | Often manual | Grace period with cleanup |
| Host controls | Client-side at best | Usually absent | Server-enforced |
| Active speaker handling | Ad hoc | Often missing | Explicit media-to-UI pipeline |
| State persistence | Minimal | Usually ephemeral | PostgreSQL plus Redis plus in-memory media |
Meetflow pays for that maturity with complexity. But the payoff is obvious. The room does not collapse the moment one participant blips. The host can actually govern the meeting. The media layer stays separate from the control layer. That is what a productized communication stack looks like.
What This Repo Suggests About Product Maturity
Meetflow still reads as an early project, but it is already thinking like a production system. The code is modular, the media plane is separated from signaling, and the state model respects the difference between durable data, live session data, and ephemeral transport objects.
That is the real takeaway. The repo is not interesting because it sends video. It is interesting because it understands that real-time products need memory, governance, and recovery, not just packets.