Pluto TV — Paramount
89.6M monthly users, 400+ live channels, and a synchronous platform doing asynchronous work.
Stack
- Go
- Apache Kafka
- gRPC
- MongoDB
- Node.js
Problem
The platform served 89.6M monthly active users across the United States and Latin America, carrying 400+ live streaming channels and more than 700,000 hours of programming. Its content management system had to present the right content, in the right region, under distribution rules that were both complex and dynamic — rules that could change while a request was still in flight. The work was fundamentally asynchronous. The services doing it were synchronous, and written in Node.js; there were more than seventy of them. Under heavy load the platform did what synchronous systems do when asked to do asynchronous work: it blocked, and the blocking cascaded.
Approach
I led backend engineering for the CMS — regional content management, user administration, advertising workflows, content distribution — and designed an asynchronous processing engine so that content presentation was governed by rules evaluated off the request path. Kafka carried the events; gRPC carried the service-to-service calls. Then I profiled the bottlenecks and migrated the performance-critical services from Node.js to Go: not as a rewrite, but service by service, where the measurements justified it, until 70+ services had moved. Unit test coverage on the Go side held above 90%, and that number is the reason the migration could be incremental rather than reckless — you can only move one service at a time if you can prove the one you moved still behaves.
The tradeoff
Rewriting in a second language splits a team's expertise and doubles the operational surface for as long as the migration runs. A full rewrite would have been cleaner on paper and reckless in practice. Migrating only where profiling showed the cost meant living with a polyglot platform for a while — a real price, paid knowingly, in exchange for never betting a delivery date on a big-bang cutover.
Impact
89.6M monthly active users · 70+ Node.js services migrated to Go
- Asynchronous processing engine delivered — non-blocking, resilient workflows under the load of 89.6M monthly active users
- 70+ Node.js microservices migrated to Go, service by service, only where profiling justified it
- 90%+ unit test coverage benchmark established across the Go services
- CMS backend delivered for 400+ live channels and 700,000+ hours of programming across the US and Latin America
- Highly concurrent Go services built on gRPC and Apache Kafka, improving performance, scalability, and operational reliability
What I learned
Language choice is rarely the actual problem, and it was not the whole problem here. The synchronous request-response shape was. Go made the fix easier to express, but the win came from moving rule evaluation off the request path — which we could have done in Node.js, more slowly. Migrate when the profile says so, never because a language is in fashion.