I've been developing in the Java ecosystem in enterprise environments for years, and the use of Spring and SpringBoot is already widely adopted. I still remember the early days with Struts, JPA, EJB… but the arrival of Spring started solving common problems across applications (security, database access, auditing…), and it became a fairly standard solution in the backend world.

At the same time that the infrastructure we deploy on has evolved, we've lost a bit of focus on optimizations, both in terms of physical memory and RAM. We’ve reached fairly high numbers with images for a simple microservice, even though we're not really using all that software.

One of the alternatives gaining traction in enterprise environments is Quarkus. Although it's a relatively young project (2019), it keeps expanding its integrations, making it a viable option to base our applications on (within the Java ecosystem).

Why should I use Quarkus?

Quarkus is based on three fundamental pillars:

If we compare Spring vs Quarkus, Spring has a gentler learning curve, greater maturity, and a wealth of configurations and libraries, which makes it slower to start and results in heavier executables and images. On the other hand, Quarkus significantly reduces memory usage, is lighter and faster, but lacks the community size and integration breadth that Spring offers.

Another advantage of Quarkus is its reactivity, which allows it to handle large volumes of requests without blocking threads, optimizing CPU and memory usage. Under the hood, it uses an event loop model based on Vert.x to avoid unnecessary blocking. It can also integrate with non-blocking messaging systems (like Kafka). The result is high-performance systems that are highly scalable and efficient.

I've done tests using the same microservice code to ensure a fair comparison (preserving the same functionality and not using native compilation). The image size is less than half, and the startup time drops from 20–30 seconds to 1–2 seconds. If we extrapolate this to a microservice ecosystem, we could significantly reduce operational costs (OPEX) and improve scalability.

Additionally, Quarkus is designed to generate native executables using GraalVM, which in my tests reduced CPU usage to 0.33% compared to a typical microservice running on a JDK image. How many resources could we save by migrating from Spring to Quarkus? Besides the direct impact on cost, more efficient cloud usage makes our solutions more sustainable and reduces their environmental footprint.

Ok, but… how do we migrate? Let’s try to create a short checklist using a sample app that exposes a REST endpoint and communicates with a database (although it’s not bulletproof).

Controller:

@Api(description = "the Products API")
@Path("/products")
@jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaJAXRSSpecServerCodegen", date = "2025-02-27T10:46:38.175609+01:00[Europe/Madrid]")
public interface ProductsApi {

    @POST
    @Consumes({ "application/json" })
    @Produces({ "application/json", "application/problem+json" })
    @ApiOperation(value = "Method to add one product to the data storage", notes = "This method creates a new product with the given body information", authorizations = {
        @Authorization(value = "adfs", scopes = {
             })
         }, tags={ "products" })
    @ApiResponses(value = { 
        @ApiResponse(code = 201, message = "Created", response = ProductResponse.class),
        @ApiResponse(code = 401, message = "Unauthorized", response = ProblemDetailsResponse.class) })
    Response createProduct(@Valid @NotNull ProductRequest productRequest);

Persistence:

@ApplicationScoped
public class ProductRepository implements PanacheRepository<ProductEntityModel> {

    public Optional<ProductEntityModel> findByIdOptional(Long id) {
        return find("id", id).firstResultOptional();
    }

    @Transactional
    public ProductEntityModel save(ProductEntityModel product) {
        persist(product);
        return product;
    }

    @Transactional
    public boolean deleteById(Long id) {
        return ProductEntityModel.deleteById(id);
    }
}
import java.math.BigDecimal;
import java.time.OffsetDateTime;

import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;

@Entity
@Table(name = "products")
public class ProductEntityModel extends PanacheEntity {

    private String name;
    private String description;

Developing:

What if I want to stick with Spring?

It’s definitely not the end of the world, but updating Spring versions helps improve compatibility and makes it easier to generate native images. Spring is gradually removing reflection from its core.

If I want to optimize and can't use GraalVM due to compatibility issues, I can turn to Spring CDS (Class Data Sharing). This is a JVM optimization that allows preprocessed class data to be shared, reducing startup time and memory usage (this is separate from GraalVM). When run for the first time, a CDS file (a sort of cache) is created for the classes.

Startup time and memory usage are significantly reduced because the JVM can load these preprocessed classes directly on subsequent runs instead of reading from .jar files. This is ideal for Java 17/21 and SpringBoot 3.x or higher.

Here’s what it might look like:

java -XX:DumpLoadedClassList=app.classlist -jar ./target/springsample-0.0.1.jar
java -Xshare:dump -XX:SharedClassListFile=app.classlist -XX:SharedArchiveFile=app.jsa -jar ./target/springsample-0.0.1.jar
java -Xshare:on -XX:SharedArchiveFile=app.jsa -jar ./target/springsample-0.0.1.jar

In the end, as software developers, we should aim to reduce costs and build more sustainable software. Additionally, optimizing our resource usage can become a competitive advantage. Choosing one framework over another depends on many factors, such as the development team's experience, the size of the solution, and the company's context.

CDS is an incremental improvement within the JVM, while GraalVM represents a deeper reengineering that provides greater benefits—but also requires more adaptation.

Tell us what you think.

Comments are moderated and will only be visible if they add to the discussion in a constructive way. If you disagree with a point, please, be polite.

Subscribe