Rearchitecting Bilibili Live Broadcast Platform: From Legacy PHP to Go with Domain‑Driven Design and Hexagonal Architecture
The article details Bilibili’s migration of its legacy PHP live‑broadcast service to Go microservices using Domain‑Driven Design and Hexagonal architecture, describing event‑storming, six‑layer tactical design, TDD, traffic‑mirroring migration, and resulting higher reliability, lower latency, and improved maintainability.
This article presents a comprehensive case study of the redesign and migration of Bilibili's live‑broadcast ("开播") platform. It begins with a background overview of the live‑streaming business, distinguishing the "watch" (C‑end) and "broadcast" (B‑end) scenarios, and explains why the broadcast subsystem is a critical backbone similar to an order system in e‑commerce.
The existing PHP‑based broadcast service suffered from heavy technical debt: tangled business logic, poor readability, outdated transaction‑script design, lack of automated tests, and an overall technology stack that no longer matched the company's direction. These issues caused high maintenance costs, frequent incidents, and difficulty in knowledge sharing.
To address these problems, the team adopted Domain‑Driven Design (DDD) as the guiding methodology. Key domain concepts such as "Domain Event", "Domain Knowledge", "Strategic Design", and "Tactical Design" are introduced, and a detailed glossary of terminology is provided. An event‑storming workshop was used to model the core broadcast use‑case, identify actors, commands, and events, and define bounded contexts (Core, General, Supporting sub‑domains).
The architectural evolution moves from a monolithic PHP service to a set of Go microservices built on Hexagonal (Ports & Adapters) architecture. The new layers include Transporter (external adapters), Data Source Adapters (repositories & infrastructure), Application (use‑case orchestration), and Domain (business logic). Design patterns shift from transaction‑script ("spaghetti code") to rich domain models with clear responsibilities.
Six‑layer tactical design introduces clean separation of concerns, enabling better testability, maintainability, and extensibility. The team also embraces Test‑Driven Development (TDD), writing unit tests first, then implementing interfaces, and finally adding integration tests. Coverage exceeds 70 % with critical paths at 100 %.
Migration is performed safely through traffic‑mirroring and event‑sourcing. Requests are duplicated to both old and new services; the new service initially runs in a read‑only mode (no side‑effects) while both services emit key events for comparison. Gradual rollout phases—event reporting, traffic mirroring, and final gray release—are orchestrated with strict SOPs.
Extensive automated testing (UTDD, ATDD) and continuous verification uncovered dozens of discrepancies and performance issues, which were resolved before full production rollout. The final system achieved higher SLA (99.99 %+), reduced latency, and improved observability via event‑sourcing dashboards.
Business outcomes include better knowledge sharing, reduced development effort, higher reliability, and a reusable migration pattern for future legacy‑to‑Go transitions. The article concludes with reflections on the importance of treating every codebase as future legacy and maintaining modern engineering practices.
Bilibili Tech
Provides introductions and tutorials on Bilibili-related technologies.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.