Skip to main content
Redhat Developers  Logo
  • Products

    Featured

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat OpenShift AI
      Red Hat OpenShift AI
    • Red Hat Enterprise Linux AI
      Linux icon inside of a brain
    • Image mode for Red Hat Enterprise Linux
      RHEL image mode
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • Red Hat Developer Hub
      Developer Hub
    • View All Red Hat Products
    • Linux

      • Red Hat Enterprise Linux
      • Image mode for Red Hat Enterprise Linux
      • Red Hat Universal Base Images (UBI)
    • Java runtimes & frameworks

      • JBoss Enterprise Application Platform
      • Red Hat build of OpenJDK
    • Kubernetes

      • Red Hat OpenShift
      • Microsoft Azure Red Hat OpenShift
      • Red Hat OpenShift Virtualization
      • Red Hat OpenShift Lightspeed
    • Integration & App Connectivity

      • Red Hat Build of Apache Camel
      • Red Hat Service Interconnect
      • Red Hat Connectivity Link
    • AI/ML

      • Red Hat OpenShift AI
      • Red Hat Enterprise Linux AI
    • Automation

      • Red Hat Ansible Automation Platform
      • Red Hat Ansible Lightspeed
    • Developer tools

      • Red Hat Trusted Software Supply Chain
      • Podman Desktop
      • Red Hat OpenShift Dev Spaces
    • Developer Sandbox

      Developer Sandbox
      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Secure Development & Architectures

      • Security
      • Secure coding
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
      • View All Technologies
    • Start exploring in the Developer Sandbox for free

      sandbox graphic
      Try Red Hat's products and technologies without setup or configuration.
    • Try at no cost
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • Java
      Java icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • API Catalog
    • Product Documentation
    • Legacy Documentation
    • Red Hat Learning

      Learning image
      Boost your technical skills to expert-level with the help of interactive lessons offered by various Red Hat Learning programs.
    • Explore Red Hat Learning
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

Ramp up on Quarkus: A Kubernetes-native Java framework

April 24, 2020
Saharsh Singh
Related topics:
JavaKubernetesQuarkus
Related products:
Red Hat build of OpenJDKRed Hat build of QuarkusRed Hat JBoss Enterprise Application Platform

Share:

    Java has been in a bit of an awkward spot since containers took off a few years ago. In the world of Kubernetes, microservices, and serverless, it has been getting harder and harder to ignore that Java applications are, by today’s standards, bloated. Well, until now. In this article, I explore the basics of Quarkus, a Kubernetes-native Java framework built to specifically address Java’s bloatedness problem.

    Java of yore

    For years, many of us looked the other way when confronted with the bloatedness of Java. Who cares if my server-side app:

    • Needed hundreds of megabytes worth of class files.
    • Created gigabytes worth of runtime memory footprint.
    • Took up to a minute (or five) to start up.

    I definitely didn’t care, because my Java application would then run reliably on a powerful piece of hardware or virtual machine for months, if not years, serving hundreds of requests concurrently. Not to mention, as a language, Java gave organizations pretty much everything they needed to maintain software for a long time using a large team of professionals with varying levels of skills.

    The Java Virtual Machine (JVM) has long promised and been delivered as a "write once, run (almost) anywhere" platform. Type safety, object-oriented programming support, and an unrivaled set of options in tooling and libraries have long made Java an excellent choice for team-based software development. Further, with enterprise-grade application servers (for example, EAP, WebLogic, and Tomcat), organizations also had a resilient and feature-rich platform for their Java web applications. These applications simply needed to comply with JavaEE standards around describing deployment concerns (think web.xml).

    Any JavaEE-compliant application server would then take care of operational concerns like security, logging, connecting to databases/queues, and scaling. It’s no surprise that for years Java has dominated the programming language landscape as the de facto standard for the enterprise.

    Kubernetes: The new application server

    It has been observed before that Kubernetes is the new application server. Containers and Kubernetes have taken the "write once run anywhere" paradigm of the JVM and extended it to most other programming languages. Now applications written in any language can leverage Kubernetes for operational concerns and decouple themselves from runtime infrastructure. These applications just have to be delivered in compliant Linux containers.

    With this structure in place, developers can code their applications in their favorite programming language and count on Kubernetes to handle operational concerns like logging, scaling, healing, and networking. Add in the Istio service mesh and you even have out-of-box fault tolerance and application-level metrics without a single line of application code. Today we find ourselves in a tech landscape that overwhelmingly prefers horizontal scaling of automated cattle over vertical scaling of manually cared for pets. Microservices and serverless/Function-as-a-Service (FaaS) applications have become all the rage, and both benefit greatly from low memory footprints and blazing-fast startup times.

    So, with all of this said, it becomes increasingly harder to ignore that my Java container images are even larger in size as well as memory footprint, and they take quite a bit longer to start up, especially when compared to a language like Golang. Modern cloud-native frameworks like Spring Boot or Dropwizard have helped, but startup times are still at least 10 seconds or more, and runtime memory footprint is at least in the hundreds of megabytes.

    Enter Quarkus

    Quarkus aims to tackle the bloatedness problem of Java head-on. Marketed as Supersonic Subatomic Java, Quarkus leverages GraalVM and HotSpot to provide developers with a framework to create applications from Java code with fast boot times and low RSS memory. The following figure from quarkus.io does a good job illustrating the benefits. Notice the drastic difference in both RSS memory and boot time between Quarkus native and the traditional cloud-native stack.

    Screen showing Quarkus metrics

    Source: ">

    OpenJDK and GraalVM

    As evident from the figure above, Quarkus has two modes: JVM and native. The native mode uses GraalVM to create a standalone executable that doesn’t run in a Java VM, and the greatest efficiency gains come from running a Quarkus application in this mode. However, not every JVM feature works in native mode, and the most notorious of these lost features is reflection.

    This fact can be a huge problem as many frameworks and libraries that Java developers depend on for everyday development rely heavily on reflection. GraalVM works around this by allowing classes to be registered for reflection at compile time. While this process can be cumbersome when working directly with GraalVM, Quarkus streamlines the registration process by detecting and auto-registering as many of your code’s reflection candidates as possible.

    While Quarkus does a pretty good job with auto-registering most reflection candidates, you might still run into instances where you have to explicitly register some of your classes using Quarkus’s RegisterForReflection annotation. This process might become more trouble than it's worth in some projects. For this reason, as well as just general flexibility, Quarkus also offers the JVM mode. In JVM mode, Quarkus apps are packaged as JAR files and run on the OpenJDK HotSpot JVM.

    Show me the code!

    So having set the stage, let’s look at some code. To get started with Quarkus, I put together a JAX-RS application following the excellent getting started guides from Quarkus. See my repo for the application's code. This application is a simple service that can be used to store, update, retrieve, and delete arbitrary text values. I mostly just followed the guide as I wrote my code. I built the application out in the following stages.

    Core application

    In this stage, I created the core application with all the API endpoints. I started by generating an app skeleton using the quarkus-maven-plugin and adding the resteasy-jackson extension for JSON support:

    mvn io.quarkus:quarkus-maven-plugin:1.3.2.Final:create \
        -DprojectGroupId=org.saharsh \
        -DprojectArtifactId=sample-quarkus-app \
        -DclassName="org.saharsh.samples.quarkus.resources.ValuesResource" \
        -Dpath="/api/values"
    
    mvn quarkus:add-extension -Dextensions="resteasy-jackson"

    Some changes I made include getting rid of .dockerignore and the Dockerfile examples generated by the quarkus-maven-plugin's create task. Instead, I prefer to use a multi-stage Dockerfile (see JVM and Native) to keep my build concerns in one file. After this, I just added my application code as captured in this tag (or commit).

    Metrics and health checks

    Metrics and health checks are crucial in creating twelve-factor applications. Quarkus leverages Microprofile, which makes adding these features pretty straightforward:

    mvn quarkus:add-extension -Dextensions="metrics"

    See this tag (and commit) for the metrics I added for the application. My application collects timing metrics for all of its exposed API endpoints. It also contains a gauge of the value store’s size. These metrics are published at the /metrics endpoint, which contains base, vendor, and application metrics. Each one of those subgroups also has its own endpoint (for example, /metrics/application):

    mvn quarkus:add-extension -Dextensions="health"

    Similarly, see this tag (and commit) for the health checks. I added a liveness check and a readiness check. The /health endpoint can be accessed for all health checks aggregated into one. However, you typically separate these into liveness and readiness probes. For this reason, /health/live and /health/ready endpoints are also automatically provided.

    Persistence

    The core app I put together in the first stage uses an in-memory storage service. This means that the storage is local to each instance of the application and gets wiped when that instance goes down. To build an actual stateless application that can be scaled up and have persistent storage, let’s offload the application state to a MySQL database:

    mvn quarkus:add-extension -Dextensions="hibernate-orm,jdbc-mysql"

    See this tag (and commit) for changes related to persistence. The highlights are:

    • Making zero code changes to switch to persistent mode because my resource class depends on the StorageService interface abstraction.
    • Picking my storage service implementation at runtime lets me introduce three things:
      • A sample.storage.type property.
      • A producer class to create the right bean based on the property.
      • A Qualifier annotation (ConfiguredStorage) for my resource class to specify that it intends to use the bean produced by the producer class.
    • Leveraging the application.properties pattern to use in-memory storage as the default storage type.

    For this last one, I intend to use environment variables to override these properties and switch over to persistent storage. There is one catch, however. Quarkus does much of its configuration and bootstrap at build time. Most properties will then be read and set during the build-time step. To change them, make sure to repackage your application. In my application.properties file, quarkus.hibernate-orm.dialect, quarkus.datasource.driver, and quarkus.datasource.health.enabled cannot be overridden at runtime. The good news is that the rest can.

    And that’s it

    I have a couple more commits around adding native build support and documentation. However, the application is ready to go. My repo's README.md does a good job of walking through the details of building and running this application locally. You can use the following steps as a reference for running the application on Red Hat OpenShift or Red Hat CodeReady Containers:

    # Create a new project
    oc new-project samples
    
    # Standup MySQL
    oc new-app --name=valuesdb  mysql-ephemeral \
        -p DATABASE_SERVICE_NAME=valuesdb \
        -p MYSQL_ROOT_PASSWORD=password \
        -p MYSQL_USER=valsuser \
        -p MYSQL_PASSWORD=password \
        -p MYSQL_DATABASE=valsdb
    
    # Create the application schema in MySQL
    oc rsh valuesdb-1-[pod_id] bash -c "mysql -uvalsuser -ppassword valsdb"
    mysql> CREATE TABLE vals (
        id BIGINT AUTO_INCREMENT PRIMARY KEY,
        value VARCHAR(255) NOT NULL,
        date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    );
    
    # Create API application from Github repo
    oc new-app --name valuesapi https://github.com/saharsh-samples/sample-quarkus-app
    
    # Expose a route
    oc expose svc/valuesapi && oc get routes
    
    # To use persistent storage, first create a secret containing DB configuration
    oc create secret generic valuesapi-properties \
        --from-literal=SAMPLE_STORAGE_TYPE=persistent \
        --from-literal=QUARKUS_DATASOURCE_URL="jdbc:mysql://valuesdb/valsdb" \
        --from-literal=QUARKUS_DATASOURCE_USERNAME=valsuser \
        --from-literal=QUARKUS_DATASOURCE_PASSWORD=password
    
    # Turn the fields of the secret into environment variables for the API app
    oc set env dc/valuesapi --from=secret/valuesapi-properties
    
    # Add liveness and readiness probes
    oc set probe dc/valuesapi --liveness --get-url=http://:8080/health/live
    oc set probe dc/valuesapi --readiness --get-url=http://:8080/health/ready

    Conclusion

    Quarkus is an exciting new development in the Java ecosystem. I will make sure to share more articles and code as I explore Quarkus in relation to serverless architecture, reactive programming, and Kafka. In the meantime, check out the following links to dig deeper:

    • Official Quarkus website
    • Official Quarkus GitHub
    • Quarkus FAQ
    • Why GraalVM?
    Last updated: February 11, 2024

    Recent Posts

    • Fly Eagle(3) fly: Faster inference with vLLM & speculative decoding

    • Kafka Monthly Digest: June 2025

    • How to configure and manage Argo CD instances

    • Why Models-as-a-Service architecture is ideal for AI models

    • How to run MicroShift as a container using MINC

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue