When we started WSO2 in 2005, there was no question what programming language was right for developing server-side enterprise infrastructure: Java. However, as we go past our 20th year and look ahead at the next 10 to 20 years, it’s clear that we need to reflect on the way forward.
Today, most of our server-side code is in Java, and the remaining bits are in Go, NodeJS, Python, and Ballerina. Since we started in Java, probably 95% of our server-side code is in Java. The use of Go and NodeJS on the server side has primarily come from the acquisition of Platformer, where they had written code in Go and NodeJS. We have also written some command-line tools, such as WSO2 Update Manager (WUM), in Go. Python has been used primarily…
When we started WSO2 in 2005, there was no question what programming language was right for developing server-side enterprise infrastructure: Java. However, as we go past our 20th year and look ahead at the next 10 to 20 years, it’s clear that we need to reflect on the way forward.
Today, most of our server-side code is in Java, and the remaining bits are in Go, NodeJS, Python, and Ballerina. Since we started in Java, probably 95% of our server-side code is in Java. The use of Go and NodeJS on the server side has primarily come from the acquisition of Platformer, where they had written code in Go and NodeJS. We have also written some command-line tools, such as WSO2 Update Manager (WUM), in Go. Python has been used primarily by our AI team for machine learning tasks and some LLM-related tasks. We have used Ballerina primarily for front-facing backend services.
Changing landscape for enterprise infrastructure software
The world has changed a lot over the past 15 years. Middleware used to be delivered as “servers” (app servers, ESBs, process servers, etc.), but with the container era, the time of independent software servers is over. Now the “serving” part is just a library that is attached to the logic, and the entire thing becomes one process that comes up to do the work and then goes away.
That is another major change over the past 5–10 years: keeping a single server up for months is no longer a critical requirement. Now, we bring up containers to handle tasks for some time and then let them go. Servers are far more ephemeral than before. Java, with its post-startup, just-in-time (JIT) optimization, doesn’t do well when servers do not run for a long time.
When containers come and go at a relatively rapid timescale, the startup time of a process matters a lot. When we say “Java”, it is now a massive ecosystem of dependencies that get pulled into it. This translates to both memory bloat and long startup times to get everything set up to run. Containers should ideally be up and ready to dance in milliseconds, not seconds.
With the growing scale of enterprise infrastructure, the reality is that the memory footprint and CPU consumption of a container are important parameters in managing cost. Again, due to massive bloat in the Java ecosystem, memory and CPU requirements for Java processes are significantly higher than for some other languages that are more native.
Java has also had to evolve with the changing landscape. The introduction of GraalVM native images, Project Loom for lightweight concurrency, and various optimization efforts show that Java ecosystems recognize these challenges. However, these solutions often feel like retrofitting a language and runtime designed for a different era. GraalVM native images are promising, but come with significant limitations, complexity, and size compared to native ones.
As a company that’s here for the long term, we think about the right direction for the next 5–10–20 years to deliver the right infrastructure for our customers. It is clear that Java is not the language of the future.
What comes after Java?
Enterprise infrastructure software that we develop can be thought of as having three somewhat distinct tiers: frontend, middle tier, and backend.
- Frontend code means code that runs inside a browser or an end-user device of some kind.
- Middle tier means code that delivers experiences for users—often called backends-for-frontends (or BFFs)—or for systems (as APIs) that provide a bridge to the capabilities of the backend.
- The backend is the core server that implements the logic of the infrastructure. Note that APIs of the backend may be directly consumable by the frontend as well, thereby negating the need for a middle tier at all.
We recently had a discussion in WSO2’s architecture leadership team and decided to think about this in the following way:
| Domain | Current | Future |
| Frontend | Web: JavaScript/Typescript, Dart iOS: Flutter, Swift Android: Flutter, Java, Kotlin | No change (*) |
| Middle tier | Java, Ballerina | Ballerina |
| Backend | Java, Go, NodeJS, Python | Go, Python |
(*) Someday, we may write another blog about the nightmare that is the frontend in terms of how fad-driven and short-lived technology choices for the frontend are.
Note that these choices are not meant to be “forever” choices. Unlike the 1990s and 2000s, when the mindset was that “one language fits all” was a viable approach, we now live in a polyglot era where languages are more function-specific. Further, in the end-game AI era, one can even ask, “Do we even bother what language is used to express the goals?”
Why Go and not Rust?
We, of course, discussed both options. Rust is a fantastic language that gives developers incredible control. If we were writing an operating system, a browser, or some code that runs for a very long time without a restart, then Rust would be a better choice.
However, we build middleware infrastructure like (API, identity) gateways and orchestrate other systems. At this level, we are always quite a bit above bare metal.
Go provides the perfect balance for that. It does memory management very well, provides sufficient low-level concurrency primitives, and cross-compiles to native code.
The added control and flexibility that Rust provides seems unnecessary and overkill for the level of systems we build. As we’ll discuss in the next section, our experience in building systems with Go has validated this choice.
Beyond just us, Go is massively proven for infrastructure software: Kubernetes is written in Go. Docker is written in Go. Many bits of enterprise infrastructure are written in Go. What that means is the Go ecosystem (both in terms of supporting libraries and deeply skilled and passionate engineers) is very healthy.
Our Go journey so far
We’ve been building systems in Go for close to a decade now, and this move is not a sudden blind jump.
OpenChoreo, now a CNCF sandbox project, is one of our most ambitious projects written in Go. It is a developer platform for Kubernetes offering development and architecture abstractions, a Backstage-powered developer portal, application CI/CD, GitOps, and observability. It is also a complete redesign and rewrite of WSO2 Choreo. Go has proven to be an excellent choice for building this Kubernetes-native platform that has to be fast and resource-efficient.
We’re currently rewriting the Ballerina compiler entirely in Go, moving away from the original Java implementation that targets the JVM. The new frontend written in Go and the Go-based Ballerina Intermediate Representation (BIR) interpreter will significantly improve compiler performance, reduce startup time, and give us better control over the tooling experience.
Thunder is a lightweight, cloud native identity platform written entirely in Go. It’s our answer to what identity and access management should look like for the next decade and beyond. Thunder leverages Go’s fast startup times and small memory footprint to deliver low-latency authentication at scale in containerized environments.
In addition to the above projects, we’ve built various command-line tools in Go (like WUM).
These projects span the full range of infrastructure software we build, from CLI tools to compilers to cloud native platforms. Go at WSO2 is already a proven foundation, not an experiment.
What does this mean for customers of WSO2 products?
We’re not abandoning our existing Java products. We’ll continue to evolve, maintain, and support our Java-based products with no end date in sight.
However, our next generation of products and platforms will be written in Go. Products like Thunder and OpenChoreo represent this new direction, bringing you faster performance, lower infrastructure costs, and more efficient resource utilization.
Thank you, Java
We want to acknowledge what Java meant to WSO2 and to all of us who’ve built our careers on it. Java gave us everything. When we started WSO2 twenty years ago, Java wasn’t just a pragmatic choice, it was the foundation that made our vision possible.
“A language that doesn’t affect the way we think about programming, is not worth knowing.”
– Alan Perlis
Every product we’ve shipped, every customer success story, every problem we’ve solved, Java was there. For many of us, Java shaped how we think about software and gave us the tools to build systems that matter.
Technology evolves and so must we. As we look ahead to Go, we do so with deep gratitude for everything Java taught us.
Thank you, Java. We wouldn’t be here without you.