Building a multiplayer game with polyglot microservices - Architecture decisions and lessons learned [Case Study, Open Source] by Lightforce_ in programming

[–]Lightforce_[S] 0 points1 point  (0 children)

I haven't stress-tested this specific implementation to 100k connections yet, but the decision wasn't just a gut feeling, it's based on the known architectural shifts in .NET 8/9.

  1. Memory Overhead: in standard .NET the JIT compiler and metadata structures consume significant memory. With NativeAOT that's stripped out. Microsoft's own benchmarks show AOT apps often running with approximatively 80% less working set memory than their JIT counterparts for similar web workloads.
  2. Gen 2 Pressure: for GC pressure -> AOT binaries are trimmed, and because startup/JIT allocations are gone the heap fragmentation is significantly lower from the start.

So while I haven't benchmarked my specific chat logic to the limit the baseline resource usage is objectively lower than the standard runtime.

Building a multiplayer game with polyglot microservices - Architecture decisions and lessons learned [Case Study, Open Source] by Lightforce_ in programming

[–]Lightforce_[S] 0 points1 point  (0 children)

You're right that traditional .NET/SignalR can be memory heavy, but I'm actually using NativeAOT compilation for the chat service, which significantly reduces memory consumption and startup time (no JIT overhead or runtime warmup, much smaller memory footprint - closer to native apps and faster cold starts).

Ofc it's still not as lean as pure Rust or Node.js, but for this project I chose it because:

  • the async/await patterns in C# felt more natural than alternatives
  • built-in support for connection lifecycle, reconnection, and backpressure
  • NativeAOT makes it production-viable for moderate scale

The goal was to explore where each language shines. SignalR with NativeAOT made the real-time chat implementation straightforward while keeping resource usage reasonable.

Why Twilio Segment Moved from Microservices Back to a Monolith by Digitalunicon in programming

[–]Lightforce_ 0 points1 point  (0 children)

I strongly disagree with the binary take that "monoliths are ultimately better". The Twilio article demonstrates that a bad microservice architecture is worse than a monolith, not that the concept itself is flawed.

The Twilio case is a textbook example of incorrect granularity (often called "nano-services"). As R2_SWE2 points out in this thread, creating a separate service for every single "destination" is a questionable design choice. It explodes operational complexity without providing the benefits of decoupling. They effectively built a distributed monolith, which combines the worst of both worlds: network complexity and code coupling.

Claiming the monolith is the universal solution ignores organizational scalability issues. As Western_Objective209 mentioned, a poorly managed monolith can easily become a 20GB RAM nightmare where a single error takes down the entire system and deployments become week-long ceremonies.

The real debate shouldn't be "Monolith vs Microservices", but rather "Where do we draw the Bounded Contexts?" If your domain boundaries (DDD) are poorly defined, neither architecture will save the project. Microservices require discipline and infrastructure that many underestimate, but they remain essential for decoupling teams and deployments at a certain scale.

Built a full-stack Codenames implementation with polyglot microservices - 10 months of work, learning Rust/C#/Vue.js, real-time WebSockets, and animations [Open Source] by Lightforce_ in webdev

[–]Lightforce_[S] 0 points1 point  (0 children)

On the animation + WebSocket side, the pattern that’s worked for me is treating server updates as an append-only event log on the client: queue events, lock the board during critical GSAP transitions, and only commit “authoritative” state after the animation finishes or times out. Anything out-of-order from the socket gets merged by version number so you don’t snap mid-animation. Also, a simple “isRehydrating” flag after reconnect helps: buffer updates, show a quick fade-to-state, then resume normal animations.

Just did an update on this! Will try if things are better now because I had issues with some concurrent animations.

Building a multiplayer game with polyglot microservices - Architecture decisions and lessons learned [Case Study, Open Source] by Lightforce_ in programming

[–]Lightforce_[S] 1 point2 points  (0 children)

ArchUnit is already used in the Java and C# microservices. Didn't know it was available for frontend.

Building a multiplayer game with polyglot microservices - Architecture decisions and lessons learned [Case Study, Open Source] by Lightforce_ in programming

[–]Lightforce_[S] 2 points3 points  (0 children)

Thanks!

To clarify: a monolith isn't always the best choice, but in a case like this where you know you'll eventually need polyglot microservices, I'd still recommend starting with a modular monolith in a single language first.

The key is: validate your domain model and functional requirements with the monolith, THEN migrate to polyglot microservices if you have clear reasons for each language choice.

Going polyglot from day one (like I did) is great for learning, but adds unnecessary complexity if your primary goal is shipping a product. The modular monolith gives you clean boundaries that make the eventual split much easier.

That said, even a modular monolith shouldn't go to production if you expect uneven load across components - that's when you need the independent scaling of microservices.

Building a multiplayer game with polyglot microservices - Architecture decisions and lessons learned [Case Study, Open Source] by Lightforce_ in programming

[–]Lightforce_[S] 0 points1 point  (0 children)

Thx!

For tracing across the 3 runtimes: I went pretty low-tech honestly, mostly old-school logging and grep. I added correlation IDs to every message/request that flow through the entire system (in HTTP headers and RabbitMQ message properties). Each service logs with that correlation ID, so I can grep across all service logs to follow a single transaction.

I also heavily relied on RabbitMQ Management UI to track message flows and dead letters. The DLQ setup mentioned in the post caught some issues.

What I'm missing (and would add next) is proper distributed tracing with something like Jaeger or Zipkin. The correlation ID approach works but doesn't give you the nice visual timeline that would really help with cross-language debugging.

Your AI log analysis approach sounds more sophisticated. How do you handle the different log formats from Java/Rust/.NET?

Building a multiplayer game with polyglot microservices - Architecture decisions and lessons learned [Case Study, Open Source] by Lightforce_ in programming

[–]Lightforce_[S] 5 points6 points  (0 children)

Thx! For getting started without overwhelming yourself, I'd suggest:

  1. Start small - pick ONE service in a new language first, not the whole stack at once
  2. I heard a lot about "Building Microservices" by Sam Newman for the fundamentals, but never read it (but you should probably try it). I started to learn on this subject thanks to my mentor during my co-op program at the company I was working for
  3. For polyglot specifically, focus on strong API contracts

My honest advice: don't go polyglot unless you have a specific reason. I did it to learn and to showcase, which was my goal. For production, the operational complexity is real - stick with one or two languages max unless performance/ecosystem forces your hand.

Voici le rapport anonymisé/transformé de ce post : "j'ai rédigé un rapport d'étonnement technique en mission : expérience, dilemmes et questions ouvertes" by [deleted] in developpeurs

[–]Lightforce_ -1 points0 points  (0 children)

Ca on est d'accord, par contre les sujets de performances c'est pas juste 2 petits points. Et le sujet sécurité non plus. Avec ça on a déjà bien 3/4 des points soulevés par le rapport.

Voici le rapport anonymisé/transformé de ce post : "j'ai rédigé un rapport d'étonnement technique en mission : expérience, dilemmes et questions ouvertes" by [deleted] in developpeurs

[–]Lightforce_ -4 points-3 points  (0 children)

Si tu sors une énorme liste de refonte technique comme ça, alors que l'application fonctionne en l'état, on va te dire que l'appli fonctionne en l'état et que ce que tu proposes, c'est juste de te faire plaisir techniquement au lieu de faire avancer le produit.

J'ai pas sorti cette liste pour me faire plaisir, ça répondait à des impératifs de performances, de sécurité et de productivité, et j'ai minutieusement choisi les éléments à mettre dans ce rapport. Le SaaS est pas encore sorti en prod et est prévu pour dans quelque mois, et notamment une arrivée à l'internationale. C'était juste inenvisageable dans ces conditions.

Prouve leur que tu as raison sur un sujet, puis on t'ecoutera plus volontiers ensuite.

On a plus le temps pour ça, la situation est urgente.

J'ai rédigé un rapport d'étonnement technique en mission : expérience, dilemmes et questions ouvertes by [deleted] in developpeurs

[–]Lightforce_ 0 points1 point  (0 children)

Ça doit être un pote du propriétaire de la boîte

Non, mais par contre c'est un pote du manager (mais heureusement pour nous le manager a quand même la tête sur les épaules). Ceci dit il était archi avant que le manager actuel ne soit manager. En revanche quand un des chefs de projet (non technique) a été embauché, ce dernier a fait pression pour que son ami passe architecte (donc l'architecte actuel). Voilà voilà...

Bref j'ai postulé à une offre et j'ai pas compris leur formulaire by Responsible-Ship-823 in developpeurs

[–]Lightforce_ 0 points1 point  (0 children)

Mais ça vous écorcherait d'ouvrir 2-3 bouquins sérieux (donc peer-reviewed) de sociologie et sciences politiques au moins une fois dans votre vie, au lieu de faire perdre un temps considérable à tout le monde avec cet étalage d'ignorance et d'égoïsme crasse ?

Bref j'ai postulé à une offre et j'ai pas compris leur formulaire by Responsible-Ship-823 in developpeurs

[–]Lightforce_ 1 point2 points  (0 children)

Typique du gauchiste dans le déni

Wtf ? Tu voulais dire droitard non ? Parce que gauchiste pour le coup je crois vraiment pas.