In modern application development and architecture, there has been a big push from monolithic, large applications that can do everything a product needs to many smaller services with a specific purpose. This onset has brought on the age of microservice frameworks (micro-frameworks) to make it easier to prototype, build, and design applications in this paradigm.
When looking at Quarkus vs. Spring Boot, each offers unique strengths to help you accomplish your goals as a microservice application developer, but which should you pick?
TL;DR




Quarkus vs. Spring Boot: What’s the Difference?
If you’re weighing up Quarkus vs. Spring Boot, it really comes down to what you’re building and where it’s running. Quarkus is built for cloud-native environments with fast startup times, low memory footprint, and smooth Kubernetes integration. Spring Boot is the tried-and-true workhorse for enterprise apps. It gives you a ton of out-of-the-box functionality, strong community support, and an easier ramp-up if you’re already in the Spring ecosystem.
What is Quarkus?
Quarkus is a Kubernetes-Native Java framework tailored for GraalVM and HotSpot, crafted from best-of-breed Java libraries and standards. The goal of Quarkus is to make Java a leading platform in Kubernetes and serverless environments. It also offers developers a unified reactive and imperative programming model to address a wider range of distributed application architectures optimally.
Some notable features of Quarkus include:
- Live coding: Quarkus offers a development mode that enables live coding, allowing developers to change their code and see the results instantly without restarting the application. This feature significantly speeds up the development process.
- Unified configuration: Quarkus provides a centralized configuration system, making managing and organizing configuration properties across the application easy.
- Reactive programming: Quarkus supports reactive programming with Vert.x, a toolkit for building high-performance, event-driven applications. This feature allows developers to create responsive and resilient systems capable of handling large amounts of concurrent connections.
- Extensibility: Quarkus has a vast ecosystem of extensions, making it simple to integrate with various technologies, libraries, and frameworks, such as RESTEasy, Hibernate, and Apache Camel.
- Native image generation: Quarkus supports generating native executables with GraalVM, resulting in faster startup times and lower memory usage than compared to traditional Java applications.
Getting Started with Quarkus
Spinning up a new Quarkus service was refreshingly fast. If you’ve ever wrestled with Spring Boot scaffolding and all the wiring that comes with it, this is a nice change of pace.
The CLI and web-based project generator make it simple to get started, you check a few boxes for the extensions you need (like Kafka, REST, Hibernate, etc.), and you have a working starter project. Run it with ./mvnw quarkus:dev, and you’re in dev mode with live reload baked in. Edit a file, save it, and it’s instantly reflected. No restarts, no waiting.
There’s very little boilerplate. You’re not buried in configuration files just to get a “Hello, world” out the door. And because it’s lightweight and designed for containers from the start, we were up and running in Kubernetes with health checks and metrics in place in less time than expected.
Learning curve? Not too steep. If you’re already comfortable in Java and have touched CDI before, most of it feels natural. And even if you’re new to it, you can ease in slowly, Quarkus doesn’t force you into reactive programming unless you need it.
Quarkus is designed for fast, efficient cloud-native deployments, while Spring Boot brings deep functionality and stability for enterprise-scale applications.
What is Spring Boot?
Spring Boot is an open-source Java-based framework used to create a microservice. It was developed by the Pivotal Team and is used to build stand-alone and production-ready spring applications. It’s a commonly chosen application framework for a microservices architecture.
Here are some notable features of Spring Boot:
- Autoconfiguration: Spring Boot automatically configures your application based on the dependencies you include, reducing the amount of manual configuration required. This feature streamlines the development process and helps developers focus on writing code rather than dealing with configuration files.
- Embedded servers: Spring Boot applications can be packaged with embedded web servers like Tomcat, Jetty, or Undertow, eliminating the need to deploy your application to an external server. This feature simplifies the deployment process and makes it easier to create self-contained applications.
- Starter dependencies: Spring Boot offers a set of pre-configured “starter” dependencies that allow developers to quickly add and configure common functionality, such as web services, data access, and security. These starter dependencies help reduce boilerplate code and ensure consistent configurations across projects.
- Actuator: The Spring Boot Actuator module provides built-in production-ready features like health checks, metrics, and application information, making it easier to monitor and manage your application in production environments.
- YAML configuration: In addition to traditional Java properties files, Spring Boot supports YAML-based configuration files. This feature offers a more human-readable and concise syntax for configuring your application.
Community and Standards
Community and standards aren’t always the first thing on your mind when picking a framework, but they matter when you’re the one maintaining that service six months (or six years) down the line.
Quarkus has two big things going for it in this area:
First, it’s backed by Red Hat, so this isn’t a flash-in-the-pan open source project, there’s real support and roadmap planning behind it. Second, it’s built on top of Eclipse MicroProfile, which means it plays well with a bunch of tools and standards already out there in the Java ecosystem.
The community has also been surprisingly solid. The docs are useful, and when edge cases are run, like the scheduler delay not being configurable, feature requests have been known to get fixed within two weeks. That kind of responsiveness promotes a lot of confidence that Quarkus isn’t just stable now but will keep evolving in the right direction.
If you’re coming from Spring, you’ll notice it’s not quite as massive a community (yet), but what’s there is focused, active, and engaged.
LogicMonitor Microservice Technology Stack
LogicMonitor’s Metric Pipeline (where we built out a proof-of-concept of Quarkus in our environment) is deployed on the following technology stack:
- Java 11 (corretto, cuz licenses)
- Kafka (Managed in AWS MSK)
- Kubernetes
- Nginx (ingress controller within Kubernetes)

Why Move From Spring Boot to Quarkus?
Our legacy pipeline was based on Spring and Tomcat. There were a couple of things about this framework choice that we didn’t like when we inherited its maintenance and deployment, including:
- Memory and CPU consumption: For the operations being performed, an inordinate amount of resources were being utilized outside of the application’s main purpose by the framework of Spring and Tomcat.
- Warmup time: The spring application could take anywhere from 10-20 seconds to start up, at which point the application could then start to warm up.
- Less code: As developers, we all hate boilerplate code. ‘Nuf said.
- Testing: Quarkus makes writing both unit and integration tests really easy. Just slap a @QuarkusTest annotation on there, and it will actually spin up the whole application to run your test.
- Scale-out (horizontal) vs. Scale-up (vertical): The smaller each application could be (resource-wise), the more we could add, horizontal scalability for the win.
- Learning curve: Quarkus’ docs online were very straightforward and easy to absorb.
How Did We Choose Quarkus Over Other Java Microframeworks?
In addition to Quarkus we also explored two other Java microframeworks: Helidon.io and MicroNaut.
Micronaut
Micronaut was probably the most comparable with Quarkus. The declarative nature of the framework was very similar, and it had out-of-the-box support for technologies we use heavily here:
- Kafka
- Docker / Kubernetes
- APIs
- Relational and non-relational databases
- Gradle
The main reason we didn’t end up with Micronaut was that it was not based on the eclipse microprofile framework, but something homegrown. We felt that since Quarkus was backed by Redhat and was based on microprofile, it had a better situation regarding community support and documentation
Helidon.io
The main reason we didn’t end up with Micronaut was that it was not based on the Eclipse microprofile framework but something homegrown. We felt that since Quarkus was backed by Redhat and was based on microprofile, it had a better situation regarding community support and documentation.
What We Learned
When we set out to build a POC of one of the applications in the pipeline, we set up an internal document laying out the success criteria:

APIs were very easy to design and implement. We went with Quarkus’ rest-easy implementation and found it to be both RFC compliant and similar to the JERSEY framework we were already familiar with in other applications in our infrastructure. However, we couldn’t use their built-in authentication implementation due to some backward compatibility issues with how the existing application authenticated requests (based on a homegrown request header token).

Kubernetes Support
One of the things we really liked about the Quarkus framework was how easy it was to set up the Kubernetes Liveness/Readiness probes. All we had to do was add a dependency (smallrye-health) and enable a configuration, and we had a kafka liveness/readiness probe ready to go. Adding our own health check to make sure our application was configured correctly was as easy as annotating a class and implementing a simple interface. Then, probes were available at the “/health” (gets both liveness and readiness check results), “health/live,” and “health/ready” endpoints.
CDI Bean Injection
In addition to the probes, we also really liked the CDI bean injection. We found this to be more easily conceptualized than Spring’s DI implementation, enabling us to build much quicker than normal. One thing to note, though, is that to expose metrics, those metrics must be exposed from a class with a bean-defining annotation. This is part of how microprofile works. More on metrics later.
Configuration
In terms of configuration, Quarkus has support for profiles and configuration from multiple sources. At LogicMonitor, we use a central configuration service, so we ended up setting System Properties based on an eagerly-instantiated bean which polled that service for its configuration settings. We didn’t have a huge use case for the @ConfigProperty annotation because we want most of our configurations to be easily changed at runtime, and those are usually defined on a bean’s instance variables. Most of the beans in our POC app were @ApplicationScoped, so that would have required the config values to be static.
Quarkus Kafka Limitations
Quarkus supports Kafka through the SmallRye Reactive Messaging framework. We had a good experience with this framework for our Kafka Producer but not our Kafka Consumer application. The Kafka Producer is fairly easy to set up for imperative usage in this guide. There are a couple of things to be careful of here regarding the default configuration values of the producer that caused a bunch of issues for us (and a few hours of troubleshooting headaches):
- Overflow Strategy: By default, the producer’s overflow strategy is that of a small memory buffer. The Kafka Emitter will wait for a signal from the Kafka consumer (reactive messaging) to know that a given message will be processed correctly. This is bad news, though, if your Kafka consumer is in a different application and unable to send any signal to the Emitter. So, we set this strategy to NONE. The risk here is that we don’t have anything within the application to know whether the Kafka consumer is keeping up. However, we solved this by directly using the Kafka client JMX metrics in our monitoring solution.

- WaitForWriteCompletion: By default, the producer was waiting for an ack from Kafka to accept the message correctly and fully, even if acks were set to 0. By default, this config value is true, so we had to set it to false to keep up with the volume of data we were processing.
When it came to the Kafka Consumer, we also ran into a fair bit of trouble in two main areas:
- Auto commit: By default, the Quarkus consumer committed to Kafka after receiving every message, causing a big pile-up in consumer lag.
- Single-threaded consumer: This caused us to actually avoid using the Quarkus Kafka consumer for metrics processing. After lots of troubleshooting hours and headaches, our team found that not only was it single-threaded, but it was also processing messages serially. It just couldn’t keep up with our volume, so we built a Kafka consumer based on the Apache Kafka Java SDK to have multiple consumer threads per application container. We did, however, keep the Quarkus Kafka consumer for another use case we had that had a much lower volume of messages simply because of the ease of use to configure it:

- Other “gotchas” with the Quarkus Kafka Consumer include:
- You have to be very careful to return a completedFuture; otherwise, we found that the reactive framework took way too long to process each message, sometimes hanging indefinitely.
- Exceptions thrown in the @Incoming method aren’t handled gracefully either (the consumer will stop), so be careful here too.
- The Reactive Messaging Framework’s channel implementation doesn’t allow the consumption of topics based on a pattern (i.e., only a single topic can be consumed per channel)

Quarkus played very nicely with our existing Java monitoring via JMX (all the garbage collection, heap, threads, and uptime DataSources were applied, and data was gathered automatically). It also allowed us to define our own application metrics easily. In my opinion, one of the biggest benefits of the app was using microprofile metrics. We were able to both time and count operations through a simple annotation that instantly makes those metrics available from a “/metrics/application” endpoint:

The @Timed Annotation gives you tons of information: min, max, mean, throughput, percentiles. This screenshot also shows the fault tolerancy feature too (which exposes its own metrics, by the way). That, along with the scheduled tasks, was a nice treat to discover (sidenote: we discovered that the initial delay of the scheduler was not configurable, so we put in a feature request, and it was fixed within two weeks!). Okay, back to metrics:
Gauges and Counters, super easy, too:

Logging in Quarkus is done via JBoss, and once we add a logging.properties file, we can tune things with no problem.
Quarkus Performance: A Huge Improvement
- CPU: After deploying, we found that Quarkus used about 15% of the CPU from the previous Spring/Tomcat solution. We were able to really scale down one of the POC application’s resource requests/limits in Kubernetes (about 200 cores worth across our infrastructure’s Kubernetes worker nodes)
- Memory: We also saw that Quarkus used about 12% of the memory from before, so we could scale down a bunch here, too (~500 GB of memory reduction across the infrastructure in this application alone)
- Startup: From 15 seconds before, we are now seeing an average of two seconds, 85% faster than before
Wrapping Up
Both Quarkus and Spring Boot are solid choices, the right one depends on your context.
If you’re in a cloud-native, containerized environment and care about startup speed, low resource usage, and tight Kubernetes integration, Quarkus is a game-changer. We saw massive gains: 85% faster startup, 15% of the previous CPU usage, and 12% of the memory, real savings at scale.
Spring Boot, on the other hand, is the go-to for enterprise apps, especially if you’re already deep in the Spring ecosystem. It’s mature, powerful, and packed with integrations, making it a great fit for complex, traditional deployments.
For us, Quarkus hit the sweet spot: lightweight, fast, and built for the kind of microservices we run. Not perfect (Kafka had some quirks), but the trade-offs were worth it.
If you’re building for the cloud and want performance without the bloat, Quarkus is worth serious consideration.

Subscribe to our blog
Get articles like this delivered straight to your inbox