Skip to content
← Work

One event bus instead of four

I co-designed and led the build of a Kafka event bus that replaced SQS, RabbitMQ, Redis queues, and SNS across a publishing platform.

Role
Co-architect and lead implementer
Company
Warner Bros. Discovery
Year
2024–2026
Stack
Kafka, KafkaJS, Node.js, AWS Lambda, S3, Datadog
messaging systems
4 → 1
services and Lambdas on the shared library
13
consumer connection delays tracked down and fixed
7–8 min

Context

The publishing platform is a set of services: a CMS, a rendering service, a web service, a content API, a job-status service, and a group of ingestion Lambdas. They talk to each other whenever content is saved, published, bulk-updated, or refreshed.

The problem

Those messages travelled over four different systems (SQS, RabbitMQ, Redis-backed queues, and SNS) with no consistent design. Each had its own failure modes, its own monitoring, and its own local setup. Adding a new consumer meant learning whichever one that corner of the platform used.

What I did

Discovery. I inventoried how messaging was used across the wider organization and wrote a requirements matrix comparing Kafka, RabbitMQ, Redis queues, and SNS/SQS.

Decisions. I co-authored the decision record for a unified event bus on the company’s managed Kafka service, which was approved. I wrote a second record for the content-feed architecture on top of it, approved by five reviewers.

Onboarding. Our platform was new to the central Kafka service. I made the first configuration changes for it (service account, environments, first topic) and worked through the access requests with the central cloud and release teams.

The library. I was the top contributor to the shared client library that every producer and consumer uses, and cut most of its releases. One piece I’m glad of: an audit-event method that never blocks the main flow and never audits its own audit events.

The migration. Each service moved behind a flag, usually dual-running old and new paths first:

  • Four ingestion Lambdas from SQS to Kafka, with batching, rate limits, and metrics.
  • The content API’s feed consumer, followed by deleting about 1,700 lines of the old SQS code.
  • The URL alias service and the job-status service.
  • The web and rendering services, which I rolled back twice before the integration held.

The hardest bug

In 2026 we saw publish messages consumed twice. The cause was that site builds ran inside the Kafka message handler. A build could take more than ten minutes, far longer than the 45-second session timeout, so the broker ejected the consumer mid-build and redelivered the message to another one.

I fixed it with job de-duplication and by tuning the session and rebalance timeouts. I also tracked down a member-ID error that caused consumers to take 7 to 8 minutes to connect.

Outcome

One event bus now carries the platform’s publish, save, bulk-update, and refresh messages. The shared library is a dependency of 13 services and Lambdas, and the team decommissioned the RabbitMQ broker in every environment.

What I’d do differently: move long-running work out of message handlers from day one. A handler should acknowledge quickly and hand the job to something built to run for minutes.

Next project

Moving TCM.com onto a shared platform