Migrating Off a Legacy Media Server
Swapping a media server platform is a real migration project. It is not a config change, and it is not a library version bump. I've watched teams walk into this thinking it's the second thing when it's actually the first, and the gap between those two expectations is where timelines blow up.
The pattern shows up the same way almost every time. A team is running a heavyweight, pipeline-style media server, the kind built on a full GStreamer pipeline framework, the sort I covered a few posts back in this series when I walked through Kurento. Someone looks at the CPU and memory footprint per stream, compares it to what a lean SFU would cost for the same fan-out workload, and proposes moving. The instinct is usually right. The plan that follows is usually too thin.
Ask what's running today, and why, before you propose the swap
The first move on any call or planning exercise about this kind of migration isn't architecture. It's history. What's running today, and why was it chosen at the time?
That second question matters more than it sounds like it should. Teams don't pick a heavyweight pipeline framework by accident. They pick it because at some point, a real requirement needed in-pipeline processing: mixing multiple camera angles into one composited output, running a computer-vision hook against the live frame, recording that happens inside the pipeline itself. A full GStreamer-based framework earns its weight when the media actually needs to be touched in flight. Nobody adopts that much complexity for no reason.
The mistake is assuming that original reason has quietly gone away just because the team proposing the migration doesn't remember it, or wasn't there when the decision got made. Sometimes it has gone away. The CV hook that justified the original choice got deprecated eighteen months ago and nobody cleaned up the architecture around it. Sometimes it hasn't. The recording pipeline is still live, it's just not the thing anyone thinks about when they're staring at a CPU graph and mentally comparing it to an SFU's leaner footprint.
Re-verify the need. Don't assume it away. That's the single highest-leverage conversation in the entire migration, and it happens before a single line of new infrastructure gets touched.
Why this is a project and not a swap
Assume the re-verification comes back clean: nothing still needs in-pipeline processing, or whatever does can be handled a different way. Even then, the migration itself is nontrivial, for four concrete reasons.
- Session and room management logic gets rebuilt. Whatever tracks which stream belongs to which session, which viewers are in which room, how state gets created and torn down, that logic was almost certainly built directly against the old framework's APIs. It called Kurento-specific or pipeline-specific constructs, and those constructs don't have a drop-in equivalent on the SFU side. This layer gets re-architected against the new platform's own model of sessions and rooms.
- Client-side signaling and SDK integration changes. However your clients negotiated sessions and exchanged signaling with the old media server, that integration is tied to the old platform's client library and its specific signaling flow. A lean SFU has its own SDK, its own signaling conventions, its own client-side connection lifecycle. That's client code that has to change, tested against real client environments, not just a server-side swap that clients never notice.
- Operational runbooks get rebuilt around new failure behavior. How you scale the old platform, what you monitor to catch it degrading, how failover behaves when an instance dies, all of that was learned the hard way against the old system's specific failure modes. A pipeline framework and a lean SFU do not fail the same way, do not scale the same way, and do not expose the same signals when something's wrong. Runbooks built for one don't transfer to the other. They get rebuilt from what you learn about the new platform's actual behavior under load, learned deliberately in testing before the first real incident forces the lesson.
- Any real in-pipeline processing needs a replacement plan before cutover. If the re-verification step turned up a genuine, still-live need, mixing, recording, a CV hook, that capability doesn't disappear just because the media server underneath it changed. It needs somewhere to live. The common pattern is standing up a separate processing service that sits alongside the lean SFU: the SFU handles fan-out, and a dedicated service subscribes to the stream it needs and does the processing work outside the media path. That's a real build, and it needs to exist and be tested before the old platform gets decommissioned, not scrambled together after.
Look at where the effort actually concentrates. It's not in the media server swap itself, provisioning a new SFU is comparatively fast. It's in the layers built on top of the old platform's specific behavior: the session logic, the client integration, the operational muscle memory, and whatever in-pipeline work has to find a new home. Underestimate any one of those and the "migration" that was scoped as a few sprints turns into a quarter, usually discovered midway through when someone finally traces a bug back to a piece of room-management logic nobody remembered was pipeline-specific.
Sequence the cutover, don't flip a switch
Once the four layers above are actually accounted for, the last piece is sequencing, and this is where the database migration comparison earns its keep a second time. Nobody cuts a production database over in one shot without a rollback path. A media server swap deserves the same discipline.
In practice that means running both platforms in parallel for a stretch, as the actual mechanism the cutover runs on. New streams get created on the lean SFU. Existing streams stay on the old pipeline framework until they naturally end or get migrated deliberately, one at a time, with a way to route a given stream back to the old platform if something about its client integration or its signaling flow turns out to be wrong in a way that didn't show up in testing. That per-stream routing decision is exactly the kind of placement logic a good migration plan designs deliberately, before the first stream moves.
The teams that get burned here are usually the ones who treated the cutover date as a hard switch: decommission the old platform, point everything at the new one, watch what breaks. That approach works fine for a change with no hidden dependencies. It works badly for a platform swap where the hidden dependencies are the entire point of this post. A parallel run with a real rollback path costs a little more calendar time up front. It costs far less than an incident on a platform you can no longer roll back from.
Treat it like a database migration
The comparison I'd want a team to sit with is a database migration, not a library upgrade. Nobody swaps a production database engine by pointing the connection string somewhere new and calling it done. You audit what's actually stored, what depends on engine-specific behavior, what breaks if a query planner behaves differently, and you plan a cutover with a rollback path. A media server swap deserves the same rigor, for the same reason: your application logic is built on top of specific behavior from the platform underneath it, and that behavior doesn't transfer just because the new platform solves the same broad category of problem.
The reward for doing this right is real. A lean SFU, once it's actually running your workload with session logic and signaling rebuilt against its model, with runbooks that reflect how it actually fails, and with any real in-pipeline need handled by a dedicated service purpose-built for it, costs meaningfully less to run per stream than a full pipeline framework carrying weight it doesn't need. That's the whole reason the migration gets proposed in the first place, and it's a legitimate reason.
The reward doesn't show up on the first attempt at a quick swap. It shows up when the team treats this as the infrastructure project it is: verify the original reason for the heavier tool is actually gone, rebuild the layers that were quietly built against the old platform's specific behavior, and give any real in-pipeline need a home before you cut over. Do that, and the migration lands clean. Skip it, and you'll rediscover every one of those four layers the hard way, usually in production, usually at the worst time.