Why did Payair Technologies switch to Quarkus?
Developing cloud-ready solutions has become an industry standard, especially in the enterprise world. Sooner or later your application has to face the problem of poor horizontal scalability or high memory usage and we all know it is better to be prepared.
We understand this at Payair as well. When we faced the challenge of preparing the backend to our mobile payment app, we decided to use frameworks supporting a serverless approach as much as possible. One of these was Quarkus.
Supersonic Subatomic Java
As creators of the framework are describing it, Quarkus is:
A Kubernetes native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.
On the Quarkus website you can find information that it has been designed around "container first" philosophy, meaning that it is optimized for fast boot times and low memory usage. As a result, we should gain near instant scale-up and high-density memory utilization in container orchestration platforms.
The way this has been achieved can be summarized as follows:
Build time metadata processing. As much processing as possible is moved into the build process e.g. all of the classes required to perform initial application deployment are used and dropped while building. They are not loaded into final JARs (and JVMs) or native executables. You can say that the framework is tailor-made for you every time you press a build button, without compromising the effectiveness of a declarative approach.
Reduction in reflection usage. Considering the point above, the resulting application contains only direct invocations. All of the fields, methods and classes that are not being called directly are purposefully removed. The same applies to dependencies as well. There is a way to include such calls (register them for reflection), but Quarkus will gently warn you that you may be deflecting from the real purpose of the framework.
Native image pre-boot. Quarkus supports native executables that can be run with GraalVM. Actually, the creators of Quarkus state that the framework was designed to be run as a native image. The ahead-of-time compilation reduces the need of dynamic scanning and loading classes into a JVM.
GraalVM. GraalVM is a native code generator which will compile your project into an executable that can be run without the JVM. You can read more about this superb project here: https://www.graalvm.org.
Below you can see a comparison of memory usage and boot time of sample applications:
Evolution, not revolution
What is interesting about this framework is that it is not revolutionary. Since some of Payair’s developers had mainly Spring experience, we were concerned that it would be difficult for them to “switch sides”. It turned out that our fear of the unknown was completely unfounded. Quarkus leverages some good old Jakarta EE standards that all Java developers are familiar with. We did not have to learn a bunch of new APIs that are advertised as "the best way to create REST endpoint" or "reinvented database access". Instead, Quarkus uses Context Dependency Injection for beans, JAX-RS for RESTful web services, JPA for database access and many others.
On top of that, Quarkus extends available Jakarta EE functionalities responding to modern world developers' demands. These are called Quarkus extensions and, to name a few, they contain support for reactive programming (but using the declarative approach), event messaging, etc.
Apart from a wide variety of available extensions, there is also a way to create your own, based on the library of your choice. Keep in mind though, that if you want to preserve those drastic optimizations that Quarkus offers, you will have to apply them manually to your extension as well.
Shout-out to MicroProfile
I would like to stop here for a second and give a big shout-out to the Eclipse MicroProfile initiative. It specifies a collection of APIs and technologies to form a baseline for quick and effective enterprise Java microservices creation. The goal of MicroProfile is to define a specification for building microservices and deliver portable applications across multiple runtime implementations.
Optimizing enterprise Java for a microservice architecture is a challenging task and, in my opinion, MicroProfile handles it pretty well. As a long term Spring developer I realized that Spring is slowly becoming the very thing it swore to destroy. The initial premises of Spring (which basically can be summed up as a lightweight alternative to Jakarta EE) are way past the expiry date now. Spring is the undisputed heavyweight champion that can handle everything you imagine but is not your best option for fast and light services. And that applies to Spring Boot as well.
It is worth mentioning how the development process of Quarkus application looks. First of all, you are not forced to use native images from day one. Normal JVM builds are still available. Resulting JARs are not as fast as native images, but still faster than your normal enterprise applications.
This leads us to the most important thing: dev mode. The special Maven plugin allows you to quickly reload classes while you are editing them, leaving an impression of hot deployment. Changing the functionality and testing it right away without further ado is a real joy. No more distracting builds and endless context switching. Pure development mode, hence the name of the plugin.
There is one more benefit of a quick startup time. Writing RESTful applications requires significant amount of integration tests on the API level. With Quarkus on board, running them gives a unit-test-smoothness feeling and if you are even a slight fan of TDD, you will appreciate the difference.
One of my personal concerns when switching from Spring to something based on Jakarta EE was lack of Spring Data JPA. I really like the mix of simplicity and functionality this module provides. But it turned out that Quarkus has my back on this one as well. There is an extension called Hibernate ORM with Panache. It is a layer on top of Hibernate ORM which focuses on simplifying ORM to the maximum without compromising the actual power that ORM gives. Panache has managed to find a sweet spot of making it trivial to work with simple entities without giving up possibilities for handling complicated use case scenarios. Bravo to Panache and adios to Spring Data!
We are yet to implement the first release of Payair’s Quarkus application into our production environment. Based on our experiences from lower level environments, we just cannot wait for it! CI/CD is no more complex than with any other framework. We only needed vigilance while setting up native build scripts. The differences between JVM and GraalVM runtimes are negligible. Moreover, our initial performance tests are looking very promising.
On the other hand Payair has many demanding customers who happen to be financial institutions. Throughout the years we have learned that they expect global reach, high performance and high availability from our products. Our solutions must be thoroughly tested, reliable and bulletproof. We are in an industry that is very risk averse and although we are aware that others are already using Quarkus in production (https://quarkus.io/blog/tag/user-story), we need to verify this for ourselves since the framework is still considered a new player on the market.
The next step is to push our Quarkus implementation to the limits to see how it behaves under a real and heavy load. For now we believe that everything will work even better than we could have anticipated. We will let you know how it went.
For more information about Payair Technologies please visit our website: https://www.payair.com
For more information on Quarkus:
Quarkus website: http://quarkus.io
Quarkus GitHub project: https://github.com/quarkusio/quarkus
Quarkus Twitter: https://twitter.com/QuarkusIO
Quarkus chat: https://quarkusio.zulipchat.com/
Quarkus mailing list: https://groups.google.com/forum/#!forum/quarkus-dev