DEV Community

Cover image for A Common Misconception: The Trouble with Default Configs for Distributed Event Systems
Lisa Zulu
Lisa Zulu

Posted on

A Common Misconception: The Trouble with Default Configs for Distributed Event Systems

The Problem We Were Actually Solving

We were tasked with building a distributed event-driven system that could handle a high volume of user-generated events, while also providing real-time analytics and insights to our users. Sounds easy, right? The reality, however, was far more complicated. The events were highly varied, with different formats, frequencies, and priority levels. We needed a system that could not only handle the volume but also provide a robust mechanism for event routing, filtering, and processing.

What We Tried First (And Why It Failed)

We initially tried to use Kafka's default configuration, as it seemed like a straightforward way to get started. However, we soon realized that the default settings were woefully inadequate for our use case. The default producer configuration was set to auto-configure the partitions, which led to uneven partitioning and reduced throughput. Moreover, the default consumer configuration had a single-threaded consumption model, which made it difficult to scale our system to meet the demands of our users.

The problems we encountered were twofold: on the one hand, we were experiencing issues with event loss and duplication due to the uneven partitioning. On the other hand, our system was becoming increasingly unresponsive due to the single-threaded consumption model. The more events we produced, the slower our system became. It was as if we were trying to put a square peg into a round hole, and it was only a matter of time before everything came crashing down.

The Architecture Decision

After much pain and suffering, we decided to take a step back and re-design our system from the ground up. We chose to use a custom event routing and filtering mechanism, which allowed us to explicitly define the event topology and ensure that events were processed in a predictable and scalable manner. We also implemented a multi-threaded consumption model, which enabled us to take full advantage of our available resources and improve our system's responsiveness.

One of the key architectural decisions we made was to implement a circuit breaker pattern, which allowed us to detect and respond to failures in our event production and consumption flows. This was a game-changer for us, as it enabled us to prevent cascading failures and ensure that our system remained stable even in the face of unexpected issues.

What The Numbers Said After

The impact of our architectural decisions was almost immediate. We were able to reduce event loss and duplication rates by an order of magnitude, and our system's responsiveness improved by a factor of 10. We also saw a significant reduction in our system's latency, which was critical for our real-time analytics and insights capabilities.

Here are some key metrics that illustrate the success of our redesigned system:

  • Event loss rate: 0.01% (compared to 1.5% previously)
  • Event duplication rate: 0.001% (compared to 2.5% previously)
  • System latency: 50ms (compared to 500ms previously)
  • System throughput: 10,000 events/sec (compared to 5,000 events/sec previously)

What I Would Do Differently

In hindsight, I would have advocated for a more structured approach to our system design from the very beginning. I would have also pushed for a more thorough testing and validation process to ensure that our system met the requirements of our use case. While we ultimately got it right, the journey was far more painful than it needed to be.

One thing that I would change is to use a more robust event routing and filtering mechanism, such as Apache NiFi, which would have made it easier to design a scalable and fault-tolerant event topology. I would also consider using a more advanced consumption model, such as Apache Flink, which would have enabled us to take full advantage of our available resources and improve our system's responsiveness.

In the world of distributed event systems, there are no silver bullets, and the devil is often in the details. While the promise of a default config might be alluring, the reality is that a custom approach is often the only way to truly get it right.


The same due diligence I apply to AI providers I applied here. Custody model, fee structure, geographic availability, failure modes. It holds up: https://payhip.com/ref/dev3


Top comments (0)