DEV Community

Cover image for Hytale Servers Will Always Stall Until We Get This One Thing Right
ruth mhlanga
ruth mhlanga

Posted on

Hytale Servers Will Always Stall Until We Get This One Thing Right

The Problem We Were Actually Solving

In hindsight, the problem wasn't just the Treasure Hunt Engine itself but how we thought we could abstract it away. We'd tried a classic read-database write-database pattern, splitting our game state into a relational database for fast, concurrent reads and a document database for slower, idempotent writes. We figured this setup would give us the best of both worlds: low latency for user queries and high write throughput for our game server, which writes state changes every few seconds.

What We Tried First (And Why It Failed)

It took us two iterations to realize the truth about this approach: the relational database had become our bottleneck. Specifically, our MySQL instance started throwing an out-of-memory error every few hours during growth events, forcing us to scale it up - which only exacerbated the problem. As we watched our costs skyrocket, we began to suspect that our schema design might be hiding a major problem. But what exactly?

The Architecture Decision

Our eureka moment came when we realized the root of the issue lay in our index design. Specifically, our primary key, which included both player ID and game ID, became the victim of a classic index fragmentation problem. As our game state grew and more players joined, our indexes became bloated, leading to slow queries and eventual crashes. We could have addressed the issue with more aggressive indexing, but that would have come at a significant cost - one we couldn't afford. So we did the unglamorous thing: we redesigned the system from scratch, this time using a NoSQL database that could handle our growth more efficiently.

What The Numbers Said After

The numbers spoke for themselves. With our new architecture, we reduced our Treasure Hunt Engine latency by 70%, increased our query throughput by 300%, and reduced our MySQL costs by a whopping 90%. We were even able to relax our freshness SLA from 5 minutes to 15 minutes without sacrificing performance. And, of course, our server stopped stalling during growth events - a welcome change for our exhausted ops team.

What I Would Do Differently

If I had to do it again, I'd take a more aggressive approach to indexing our schema. With the benefit of hindsight, I see that we could have optimized our primary key without sacrificing our NoSQL scalability. But in the world of engineering, hindsight is always 20/20 - and sometimes it's better to take an educated risk than play it too safe.

Top comments (0)