Quarkus Vs Micronaut: A Feature And Performance Comparison

Quarkus vs Micronaut
How does the Quarkus framework compares with Micronaut: features / library compatibility, the first response time and the memory footprint.

Introduction

Quarkus and Micronaut are modern Java frameworks that can be used to build microservice and serverless applications tailored for JDK and GraalVM.

While Quarkus is backed by Red Hat, Micronaut is developed by the creators of the Grails framework and sponsored by Object Computing, Inc..

Development of Quarkus started on early 2019, the 1.0.0 version was released on November 2019. Micronaut development started on early 2018, the 1.0.0 version was released on October 2018.

Both Quarkus and Micronaut are open source under the Apache License 2.0.

Features

While Quarkus is more reliant on Java EE and Eclipse MicroProfile APIs, Micronaut defines it's own APIs and is more inspired by the Spring and Grails frameworks.

Quarkus is based on an extension architecture that makes it easy to integrate third party frameworks. You can for example use Spring DI, Web and Data JPA annotations in your Quarkus applications.

Micronaut provides an Aspect Oriented Programming (AOP) implementation that does not use reflection to define cross cutting concerns (logging, ...).

Dependency Injection and Inversion of Control

Quarkus implements a subset of the Contexts and Dependency Injection (CDI) specification. Supported DI features and limitation can be viewed here.

Micronaut uses a simpler compile time dependency injection implementation that only uses reflection as a last resort and avoids proxies. A full Micronaut IoC guide is available in this page.

Reactive and declarative programming

Both Quarkus and Micronaut support reactive programming.

Quarkus supports both Netty and Vert.x as reactive engines that are based on an event-driven architecture with non-blocking IO. Reactive Messaging is supported with Apache Kafka and AMQP. Reactive MySQL, PostgreSQL and MongoDB clients are also available. An alternative declarative way to implement HTTP endpoints is possible with Reactive routes.

Micronaut includes both non-blocking HTTP server and client APIs based on Netty. Reactive MySQL and PostgreSQL clients are supported via third-party libraries. Apache Kafka and RabbitMQ are also supported with Reactive APIs.

Resilience & Fault tolerance

To enable resiliency, Quarkus contains an implementation of the MicroProfile Fault Tolerance specification to provide Retry, Timeout, Fallback, and Circuit Breaker capabilities (as demonstrated in the following guide).

Micronaut also supports the Retry, Fallback, and Circuit Breaker patterns as AOP advices.

Cloud

Quarkus primarily targets Kubernetes cloud environments. Automated generation of Kubernetes resources is provided out of the box. Experimental serverless support is available for AWS Lambda and Azure Functions.

Micronaut provides natively support to many cloud features:

  • Distributed Configuration with:
    • HashiCorp Consul
    • HashiCorp Vault
    • Spring Cloud Config
    • AWS Parameter Store
  • Service Discovery with:
    • Consul
    • Eureka
    • Kubernetes
    • AWS Route 53
  • Serverless Functions: many features are provided to make it easier to write functions, run and deploy them to Function as a Service (FaaS) providers such as AWS Lambda or dedicated containers such as OpenFaaS.

Language Support

While Quarkus provides support to Java, Kotlin and Scala, Micronaut comes with first-class support for Java, Groovy and Kotlin.

Kotlin is a cross-platform statically typed language that is highly interoperable with existing Java libraries and allows writing concise code. It's also the official language for Android app development.

Scala is a multi-paradigm language with a strong static type system that provides language interoperability with Java and offers a more elegant code syntax.

Groovy is a dynamic and optionally typed JVM language with static compilation capabilities that aims to provide an easy to learn syntax.

Tooling

Quarkus provides an on online project generator with configurable dependencies: https://code.quarkus.io/. It also provides live reload capabilities for the GraalVM native build mode.

Micronaut projects can be generated using the command line.

References

Performance

The tests were performed using JDK 8 from Oracle and OpenJDK 11 from AdoptOpenJDK. Both the Quarkus and Micronaut demo app's are minimal and expose a simple hello endpoint. For those interested, the code source of the demo apps can be found here: quarkus-hello-demo, micronaut-hello-demo.

Time to first request

To measure more accurately how long a framework needs to start responding to requests, this Node.js script was used to start the demo apps and calculate the time it takes to respond successfully to the first request.

const spawn = require("child_process").spawn;
const request = require("request");

const pingIntervalMs = 100;

const args = process.argv.slice(2);
if (args.length == 0) {
  console.log('The path of java executable jar must be specified !');
}

const proc = spawn("java", ["-jar", args[0]]);

const startTime = new Date().getTime();
const intervalHandle = setInterval(() => {
  request("http://localhost:8080/hello", (error, response, body) => {
      if (!error && response && response.statusCode === 200 && body) {
          const time = new Date().getTime() - startTime;
          console.log(time + " ms");
          clearInterval(intervalHandle);
          proc.kill();
          process.exit(0);
      } else {
          // @ts-ignore
          if (!error || !error.code === "ECONNREFUSED") {
            console.log(error ? error : response.statusCode);
          }
      }
    }
  );
}, pingIntervalMs);

The script was lauched 5 times with each of the demo apps using JDK 8 and OpenJDK 11. The results are displayed below:

Time to first request - JDK 8 - Quarkus vs Micronaut
Time to first request - OpenJDK 11 - Quarkus vs Micronaut

On average, Quarkus took 2049 milliseconds to respond to the first request, while Micronaut took 5228 milliseconds.

Load tests were also performed by executing 100 requests, with a maximum of 10 parallel requests. Quarkus has clearly a better response time and a lower latency (time to first byte) as demonstrated by the following illustrations:

Load test - Micronaut

Load test - Quarkus

Memory footprint

The VisualVm tool was used to monitor the memory usage of both demo apps after starting them up and executing 100 requests, then performing a GC manually.

Memory usage - Micronaut
Memory usage - Quarkus

In this example, Quarkus uses less memory then Micronaut, this can be explained by the lower loaded classes.