My day job is being a lead software developer engineer, building JVM-based microservices (Kotlin, Micronaut, Kubernetes, Kafka, ScyllaDB). Seeing as how I work professionally with the JVM, when developing a backend server for my small-scale MMO, I prefer to write the server in Java/Kotlin.
The unfortunate aspect about wanting to write a game server on the JVM is that most game engines don't support the JVM.
I happen to be using GodotEngine, which features its own Python-esque GDScript, or you can use C#. I figure I can learn enough C# to handle the networking, but I wouldn't want to write the server in C#. I love Kotlin. I'm proficient in Kotlin.
Arguably your network stack is the most important part of an MMO, in that it can make or break your player experience. I've played normal multiplayer games who have crappy netcode and it is painfully obvious.
This seems to be an age-old (debates going back to 2000s at least) religious debate. I feel like there is a majority perspective saying UDP is required for best performance, but at the same time there are MMOs successfully implementing TCP (World of Warcraft).
I won't go too much into this as there are a TON of google results, but essentially the problem to solve seems to be latency, packet loss, retries, TCP overhead associated with this stuff, and how for things like movement you only care about the last packet and it is probably ok to drop a few.
Going UDP, you end up having to implement your own solution on top for ordered and reliable packets. I came across KCP (ARQ implementation?) which looked like a good fit for my purposes, and also featured both C# and JVM implementations.
This topic alone is huge and you can easily spend a week going down rabbit holes. Are you able to utilize a service or out-of-the-box paid library/system? SpatialOS, SmartFoxServer2X, Proton and others solve this, if your code fits into their model and you are okay paying the money.
I wanted free/open source networking libraries, but the requirement for JVM and C# made things more complicated.
The list goes on, but as I started to look into all of these, they all didn't fit for one or more reasons. Either they were ancient, had no C# implementation (that was current), had no JVM implementation (that was current), weren't actively maintained in general, were only implemented in one language and not another, JNI/JNA bindings didn't work/couldn't figure out, or just on and on.
One of the first solutions I landed on which checked most of my boxes was SmartFoxServer2X. It had a server-side Java implementation and multiple client language implementations. It was looking pretty good at first.
As I dove deeper into trying to implement, I realized I didn't like the low-level threading design, where I had to work with synchronized everything, and after reading some confirmation-bias articles, the underlying design seemed a bit "old school" (e.g. locking threads everywhere versus disruptor pattern/reactor).
I realized I didn't like how I had to implement my code by dropping jars into the server lib directory, versus including SFS2X as a library in my app code. It is workable of course, but I preferred to build a fat/uber jar and Dockerize it.
Realizing that I should use Akka with its actor model implementation for shared, mutable state, I decided to continue my search for an open source network stack and implement my own stuff for handling AoI and event/message based networking.
I came across KCP which uses UDP and builds on top of it an ordered, reliable layer, promising greater performance than TCP. There are a couple of JVM implementations, as well as C#.
I did finally get a basic client/server working, but it was a learning curve and a bit of working with the lower level Netty objects. I may still come back to this, but after considering how I would still want encryption and session management, I decided to continue my search for a TCP-based networking stack.
My latest discovery which I am currently working on implementing is RSocket, a reactive TCP socket implementation which also supports websockets. This has implementations is many different languages making it a good fit. I've also been able to understand how I can utilize protocol buffers.
Equipped with the RSocket library and Akka Typed, I've been able to create an early stage server, which processes incoming commands (messages) from clients using Protocol Buffers on a reactive stream, and passes these to an Akka actor which maintains the server state.
After going down this route, and reading and watching more (youtube, etc), it seems this probably wont scale well. Or rather there are a lot more tricks to implement to avoid garbage collection.
I got sidetracked from the Kotlin solution and started to dive into Rust(lang), which happens to have bindings for Godot as well. And has some networking libraries available. And some ECS frameworks.