DEV Community

Markus
Markus

Posted on • Originally published at the-main-thread.com on

Enterprise Java Supply Chains: Spring, Quarkus, Tanzu, and RHBQ Compared

Hero Image

When developers compare frameworks, the debate usually focuses on features, performance, or startup time. Those matter, but they’re not the whole story. There’s a more fundamental question that cuts deeper than benchmarks:

Who takes responsibility for the code you run?

It’s not just a matter of convenience. The provenance of your dependencies determines how quickly you can patch vulnerabilities, how reproducible your builds are, and how much hidden risk you pass downstream to your customers.

Choosing a framework is never just a technical decision. It’s a question of trust, responsibility, and the kind of codebase you want to leave behind. It also includes practical considerations like supported configurations and lifecycle guarantees.

Both Spring Boot and Quarkus have vibrant open-source communities. But most enterprises eventually face a choice: stay with community builds, or adopt an enterprise distribution such as Tanzu Spring (Broadcom/VMware) or the Red Hat Build of Quarkus (RHBQ). In this article, we’ll compare the different approaches and see how they stack up.

Disclaimer: This overview is based on the linked, public sources and my own experience. I’ve aimed for balance, but if you spot inaccuracies on either side, please let me know — in the comments, on social, or via email — and I’ll happily correct them.

This article:

  1. Explains the difference between the Red Hat build of Quarkus and community Quarkus.

  2. Shows how that model compares to Spring Boot ’s approach.

  3. Walks through a hands-on example using the same codebase for both Spring Boot and RHBQ to illustrate the practical differences.

  4. Gives you a high level overview about the Enterprise support offerings and how they compare.

Community Builds: Fast, Open, but Short-Lived

Spring Boot and Framework releases are published directly to Maven Central. Dependencies like Jackson, Tomcat, and Hibernate are pulled unchanged from their upstream projects.

The community support window is short, typically one year per line. Once that window closes, CVEs are no longer patched and you need to upgrade. While the Spring Boot BOM keeps versions aligned, every artifact remains an upstream binary. The Spring release planning is mapped out on a calendar.

Quarkus follows a similar model. The release roadmap is developed openlyon GitHub, and you can see when a major, minor, or patch release is targeted.

The Quarkus community moves quickly, often shipping new minor releases every few months. That innovation comes at the cost of no formal long-term support guarantee. If you rely solely on the community, you’re expected to keep up with the cadence.

Key highlights:

  • Spring OSS: ~1 year support per line, Maven Central binaries.

  • Quarkus OSS: open planning, fast cadence, no LTS guarantee.

  • Both: great for experimentation and innovation, not ideal for regulated enterprises.

Tanzu Spring (Broadcom/VMware)

Tanzu Spring productizes the entire Spring portfolio with over 50 projects (Framework, Boot, Data, Cloud, Security, Batch, Integration, etc.), plus Apache Tomcat (via Tanzu tc Server) and OpenJDK (via BellSoft Liberica).

Support lifecycle

  • Every minor release : 24 months of support.

  • Final minor of each major: 5 additional years.

  • Example: Spring Boot 2.7 , released May 2022, supported until end of 2026 Lifecycle Docs.

Patch process

When a CVE hits a dependency like Jackson or Tomcat, Broadcom updates the BOM and ships a new Spring Boot or Framework patch release. You adopt that patch, which may also bring unrelated upgrades.

Tooling

Supported platforms

  • Linux and Windows , across VMs, containers, and Kubernetes.

  • Supported as long as the underlying OS vendor still provides security updates. (my interpretation!)

  • Probably best integrated with VMware’s own Tanzu/VM offerings

Highlights:

  • Up to 7 years of support.

  • Enterprise binaries from Broadcom’s private repo (repo.spring.vmware.com). (Guides)

  • Patch delivery = BOM-level patch releases.

  • Broad cross-platform support.

Red Hat Build of Quarkus (RHBQ)

RHBQ takes a supply chain–centric approach: every artifact is rebuilt from source by Red Hat , including all transitives, and tagged with a .redhat-xxxxx suffix. This guarantees provenance and allows surgical CVE fixes. The supported components and their support levels can be accessed on the customer portal.

Support lifecycle

  • Each major supported for ~ 3 years : ~2.5 years Full Support + 6 months Maintenance (RHBQ Lifecycle).

  • Example: Quarkus 3 , GA Oct 2023 → supported until Oct 2026.

Patch process

When a CVE hits, Red Hat backports and rebuilds just the affected artifact. Customers get a new .redhat jar in the same stream. No unrelated dependency churn.

Tooling

  • Quarkus CLI for project upgrades (blog)

  • Quarkus VSCode extension (marketplace)

  • Migration Toolkit for Applications (MTA)

Supported platforms

  • Certified on RHEL and OpenShift.

  • Supported on Windows Server (x86_64) with Adoptium JDK.

  • Comes with UBI base images and Mandrel native image builds optimized for RHEL.

Highlights:

  • ~3 years of support per major.

  • All artifacts rebuilt, .redhat suffix ensures traceability.

  • Surgical CVE patching without BOM churn.

  • Supported on Linux (Adoptium), RHEL, OpenShift, and Windows.

Why This Matters: Dependency Provenance

In the community model (Quarkus or Spring Boot), you consume artifacts published by dozens of upstream maintainers. The framework BOM aligns versions, but ultimately you are running whatever those projects shipped to Maven Central.

That works until a CVE or compliance audit arrives. Then you discover that no single party takes responsibility for the whole chain. You wait, you juggle versions, you hope nothing else breaks. The risk shifts downstream: To you.

In the RHBQ model:

  • Red Hat owns the full dependency graph for your runtime.

  • Every artifact is rebuilt from source, scanned, tested, and versioned together.

  • When a CVE is discovered, Red Hat doesn’t shrug and wait. It applies the fix and reissues the affected jar, leaving everything else untouched.

The difference is simple but profound: one model outsources responsibility to dozens of maintainers; the other accepts accountability on your behalf.

Hands-On: One Codebase, Two Runtimes

Let’s build a tiny REST API once with Spring Boot, and once with RHBQ. Using the same source code thanks to Quarkus’s Spring compatibility layer. And yes, I would have loved to do this with the Tanzu Spring dependencies but I do not have access to the customer binaries.

This isn’t about “Hello World tricks.” It’s about proving that developers can take what they know today and run it under a model that respects their time and their responsibility to deliver secure, stable systems.

Prerequisites

  • JDK 17+

  • Maven 3.8+

  • Git (optional)

Create a new Maven Project

mvn archetype:generate -DgroupId=com.example.app -DartifactId=community-app -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.5 -DinteractiveMode=false
cd community-app
Enter fullscreen mode Exit fullscreen mode

If you want to, you can grab this little example from my Github repository and play around with it.

Shared Source Code

src/main/java/com/example/app/GreetingService.java

package com.example.app;

import org.springframework.stereotype.Service;

@Service
public class GreetingService {
    public String greet(String name) {
        return "Hello, " + (name == null || name.isBlank() ? "world" : name) + "!";
    }
}
Enter fullscreen mode Exit fullscreen mode

src/main/java/com/example/app/GreetingController.java

package com.example.app;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class GreetingController {

    private final GreetingService svc;

    public GreetingController(GreetingService svc) { this.svc = svc; }

    @GetMapping("/greet")
    public String greet(@RequestParam(required = false) String name) {
        return svc.greet(name);
    }
}
Enter fullscreen mode Exit fullscreen mode

This uses standard Spring annotations. When you run it on Quarkus, they are maped internally with quarkus-spring-web and quarkus-spring-di.

Spring Boot Build

Spring Boot pom.xml, main class, run with mvn spring-boot:run.

Inspect dependencies: plain upstream artifacts from Maven Central.

pom.xml for Spring Boot

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>spring-boot-app</artifactId>
  <version>1.0.0</version>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.5</version>
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
  </dependencies>
</project>

Enter fullscreen mode Exit fullscreen mode

Add a Spring Boot main class:

src/main/java/com/example/app/Application.java

package com.example.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

Run:

mvn spring-boot:run
Enter fullscreen mode Exit fullscreen mode

Open: http://localhost:8080/api/greet?name=Spring

Inspect dependencies:

mvn dependency:tree 
Enter fullscreen mode Exit fullscreen mode

Output excerpt:

org.springframework.boot:spring-boot-starter-web:3.2.5
├─ org.springframework:spring-webmvc:6.1.6
├─ org.apache.tomcat.embed:tomcat-embed-core:10.1.20
├─ com.fasterxml.jackson.core:jackson-databind:2.15.4
├─ ch.qos.logback:logback-classic:1.4.14
└─ org.apache.logging.log4j:log4j-to-slf4j:2.21.1
Enter fullscreen mode Exit fullscreen mode

These are upstream artifacts from Maven Central and they have no vendor suffix.

Red Hat Build of Quarkus Build

pom.xml for RHBQ. Make sure to rename the Application.java to Application.java_ so it won’t be compiled.

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>quarkus-rhbq-app</artifactId>
    <version>1.0.0</version>

    <properties>
        <compiler-plugin.version>3.11.0</compiler-plugin.version>
        <quarkus.platform.group-id>com.redhat.quarkus.platform</quarkus.platform.group-id>
        <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
        <quarkus.platform.version>3.20.2.redhat-00002</quarkus.platform.version>
        <surefire-plugin.version>3.1.2</surefire-plugin.version>
        <skipITs>true</skipITs>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>${quarkus.platform.group-id}</groupId>
                <artifactId>${quarkus.platform.artifact-id}</artifactId>
                <version>${quarkus.platform.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <repositories>
        <repository>
            <id>red-hat-enterprise-maven-repository</id>
            <url>https://maven.repository.redhat.com/ga/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>red-hat-enterprise-maven-repository</id>
            <url>https://maven.repository.redhat.com/ga/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <dependencies>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-spring-di</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>${quarkus.platform.group-id}</groupId>
                <artifactId>quarkus-maven-plugin</artifactId>
                <version>${quarkus.platform.version}</version>
                <extensions>true</extensions>
                <executions>
                    <execution>
                        <goals>
                            <goal>build</goal>
                            <goal>generate-code</goal>
                            <goal>generate-code-tests</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${compiler-plugin.version}</version>
                <configuration>
                    <compilerArgs>
                        <arg>-parameters</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${surefire-plugin.version}</version>
                <configuration>
                    <systemPropertyVariables>
                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                        <maven.home>${maven.home}</maven.home>
                    </systemPropertyVariables>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
Enter fullscreen mode Exit fullscreen mode

Run in dev mode:

quarkus dev
Enter fullscreen mode Exit fullscreen mode

Open: http://localhost:8080/api/greet?name=Quarkus

Inspect dependencies:

mvn dependency:tree 
Enter fullscreen mode Exit fullscreen mode

Output excerpt:

io.quarkus:quarkus-spring-web:3.20.2.redhat-00003
├─ io.quarkus:quarkus-arc:3.20.2.redhat-00003
├─ io.vertx:vertx-core:4.5.16.redhat-00009
├─ io.netty:netty-codec-http:4.1.121.Final-redhat-00002
├─ com.fasterxml.jackson.core:jackson-databind:2.18.2.redhat-00004
└─ org.jboss.logging:jboss-logging:3.6.1.Final-redhat-00001
Enter fullscreen mode Exit fullscreen mode

Almost every artifact carries a .redhat-xxxxx suffix, showing it was rebuilt in Red Hat’s supply chain. And I personally only know one exception to this rule :) Comment on the article if you have found it yourself.

Comparing the Two Trees

diff the dependency trees:

mvn dependency:tree > spring-tree.txt
mvn dependency:tree > rhbq-tree.txt
diff -u spring-tree.txt rhbq-tree.txt | less
Enter fullscreen mode Exit fullscreen mode
  1. Provenance

  2. Security patching model

  3. Dependency graph stability

The Spring Boot tree represents the community ecosystem. Flexible but dependent on upstream cadence. The RHBQ tree represents an enterprise-controlled ecosystem. Every jar comes from a single vendor pipeline, ensuring traceability, backporting, and predictable behavior in production.

When a CVE Hits

Scenario: CVE in com.fasterxml.jackson.core.

  • Spring Boot path: wait for the Jackson project to fix → wait for Spring Boot BOM update → upgrade Spring Boot.

  • RHBQ path: Red Hat patches & rebuilds → releases updated .redhat artifact within same stream → no unrelated churn.

Every unpatched CVE is not just a technical inconvenience, it’s a liability. It risks customer data, compliance standing, and reputation.

One model leaves you waiting while risk accumulates. The other takes direct responsibility to close the gap.

Why Developers Should Care

Both ecosystems provide a viable enterprise path, but they optimize for different goals:

  • Spring OSS is excellent for rapid development and innovation, but short support windows demand frequent upgrades.

  • Quarkus OSS gives early access to cutting-edge features, with open release planning and transparency, but no lifecycle guarantees.

  • Tanzu Spring offers stability and breadth. If your enterprise is standardized on Spring, Tanzu is the natural choice. Expect long lifetimes (up to 7 years), but patches come as BOM-level updates. You will need processes to handle dependency churn.

  • RHBQ offers control and provenance. If you run on RHEL or OpenShift, RHBQ aligns perfectly: every jar is vendor-rebuilt, patches are surgical, and builds are fully certified. The trade-off is a slightly shorter lifetime.

Recommendations:

  • Choose Tanzu Spring if: Your organization is already deeply locked into Spring, believes guaranteed long-term support outweighs agility, and accepts the responsibility that comes with BOM-level upgrades.

  • Choose RHBQ if: You need surgical CVE patching , supply-chain provenance , and the confidence of vendor certification , including deep integration with Red Hat platforms.

  • Stay on community builds if: you can afford rapid upgrades, want early access, or are in non-critical environments.

Thanks for reading The Main Thread! Subscribe for free to receive new posts directly in your inbox.

Top comments (0)