eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Overview

In the last few years, there has been a lot of effort in the Java ecosystem to improve JVM performance. We have seen the JIT compiler, then the Ahead of Time (AoT) Compilation, and lately the Native Images.

Popular Java frameworks, like Micronaut and Spring, have moved in the same direction to achieve better performance through compilation improvements. Spring offers both Ahead of Time and Native Image support. However, in such big frameworks, there is still a lot of use of Reflection, so there is still plenty of room for improvement. The latest feature, to be introduced in Spring Boot 4, is an AOT optimization for Spring Data, with the AOT Repositories.

In this article, we’re going to see what the new feature of Spring Data AOT Repositories brings in. Then, we’ll demonstrate how it works. In the end, we’re going to compare its usage with the current alternatives, using Spring Boot 3 with and without AOT compilation.

2. Dependencies

Let’s start by defining the minimum dependencies possible, for demonstrating the Spring Data AOT Repositories. We can only keep the spring-boot-starter-web and spring-boot-starter-data-jpa. The first is for offering an endpoint to verify that the repository actually works, and the latter contains everything needed for Spring to interact with a database:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>4.0.5</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>4.0.5</version>
</dependency>

Spring Boot major version 4 is only available in early stages. We’re still going to use the stable 4.0.5 for our demonstration.

3. Spring Data Repository

Moving on, let’s look at how repository implementations have evolved from being runtime proxies to the build-time generated code with Spring Data AOT Repositories. We’ll use a very simple and popular example of a User entity and the respective UserRepository. This will let us compare behavior and performance across the three options of repositories without AOT, repositories with AOT (but before AOT Repositories), and AOT Repositories.

3.1. The Domain Model

We’ll use a short User entity, with just three fields, for demonstration purposes:

@Entity
@Table(name = "USERS")
public class User {
    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    // constructors, setters, getters, equals, etc.
}

The entity class only contains an id, a firstName, and a lastName field. We can use all of the Spring Data and JPA annotations we’re familiar with. Then we’ll create the related UserRepository:

public interface UserRepository extends Repository<User, Long> {

    User save(User user);

    @Transactional(readOnly = true)
    List<User> findAll();

    List<User> findAllById(Iterable<Long> longs);

    @Query(value = "SELECT * FROM users", nativeQuery = true)
    List<User> nativeQueryFindAllUsers();

    @Query(value = "SELECT u FROM User u")
    List<User> queryFindAllUsers();
}

First, we’ll include three methods that Spring Data can translate into queries, as normal. On top of that, we’ll add two more methods annotated with @Query, one native and one non-native. This is so we see how Spring Data AOT Repository handles the different cases.

Second, we extend the Repository Interface to be more generic. The dependency we’ve included earlier will translate it to JpaRepository.

3.2. Spring Data Repositories Without AOT

Before Spring AOT optimizations and Spring Data AOT Repositories, we would compile the code by using the mvn clean install command. This would convert the Java file to a class, without any changes, except for indentation.

This means that the implementation is not generated. As we know, everything happens at runtime:

  1. Spring finds the Repository interfaces
  2. Passes them to the JpaRepositoryFactory
  3. The JpaRepositoryFactory builds the SimpleJpaRepository instances
  4. Then wraps each instance with a dynamic proxy that routes calls from your interface methods, like findAll(), to the corresponding methods on SimpleJpaRepository, or to the Query and JPQL implementations, or to any custom implementations

Everything is being built at runtime, based on reflection. This means that startup time and memory are being affected.

3.3. Repositories With AOT, Before Spring Data AOT Repositories

Spring 6 came with Ahead of Time Optimizations. To enable this feature, we need to:

  • Compile the code, including the spring-boot:process-aot task, or set up the build plugin to enable AOT compilation by default
  • Execute the application setting the spring.aot.enabled property to true

Regarding the Spring Data Repositories, the result is the same as before. This means that we get the same class, and then Spring uses the SimpleJpaRepository, reflection, and proxies at runtime to make everything happen. The difference is that the AOT compilation creates an additional class, the UserRepository__BeanDefinitions class, with some reflection metadata and other info precomputed at build time. This improves startup time.

3.4. Spring Data AOT Repositories

The new feature, coming with Spring Data 4, is the Spring Data AOT Repositories. With this feature, Spring is shifting all the Repository preparations that are done at application startup to build time.

Let’s see how this works, on a high level. Spring turns your Repository query methods into actual source code by relying on the store-specific nature of the repository. The methods that are already implemented are used directly. For instance, the save() method is implemented in SimpleJpaRepository, in our example. Spring doesn’t need to generate any code for such methods. However, the remaining methods will be implemented inside the UserRepositoryImpl__AotRepository class.

The way to compile the code using AOT remains the same as in the previous Spring version. We can find the generated classes in our target/classes folder:

@Generated
public class UserRepositoryImpl__AotRepository extends AotRepositoryFragmentSupport {
    private final RepositoryFactoryBeanSupport.FragmentCreationContext context;
    private final EntityManager entityManager;

    public List<User> nativeQueryFindAllUsers() {
        String var1 = "SELECT * FROM users";
        Query var2 = this.entityManager.createNativeQuery(var1, User.class);
        return var2.getResultList();
    }

    public List<User> queryFindAllUsers() {
        String var1 = "SELECT u FROM User u";
        Query var2 = this.entityManager.createQuery(var1);
        return var2.getResultList();
    }
}

Methods annotated with @Query contain the same code we would write if we weren’t using Spring Data. The UserRepository__BeanDefinitions class is present, similar to previous versions. The last source generated by this new feature is a JSON file with hints for native-image, UserRepository.json.

This way Spring generates a concrete repository implementation at build time, eliminating the proxy and most runtime reflection. This improves both the startup time and memory.

To enable usage of Spring Data AOT Repositories, we need to execute the application setting the spring.aot.repositories.enabled property to true:

mvn spring-boot:run -Dspring.aot.enabled=true -Dspring.aot.repositories.enabled=true

4. Performance Implications

Spring Data AOT Repositories are expected to improve application performance. Startup time should be reduced, and some memory consumption as well, as advertised in the relevant Spring Blog article:

spring data aot repositories benchmark

Next, we’ll compare the performance of the three implementations we discussed so far:

  • Spring before AOT, using the java -jar spring-data-jpa-not-aot/target/spring-data-jpa-not-aot-0.0.1-SNAPSHOT.jar command
  • Spring with AOT improvements, using the java -Dspring.aot.enabled=true -jar spring-data-jpa-aot/target/spring-data-jpa-aot-0.0.1-SNAPSHOT.jar command
  • Spring Data AOT Repositories, using the java -Dspring.aot.enabled=true -Dspring.aot.repositories.enabled=true -jar spring-data-jpa-aot-repository/target/spring-data-jpa-aot-repository-0.0.1-SNAPSHOT.jar command

We’ll use five entity classes and repositories to try to make the changes more visible. And we’ll focus on the startup time and memory consumption.

4.1. Build Times Comparison

As already explained, the new AOT Repositories feature performs additional work at build time to construct the Repositories. So, this means that we expect slower build times when we enable this feature:

  • repositories without AOT: Total time: 11.076 s
  • repositories with AOT: Total time: 17.166 s
  • AOT Repositories: Total time: 25.390 s

With Spring Data AOT Repositories, if we have syntax errors in JPA methods, we see compile-time errors. This makes sense, since the transformation of JPA methods to SQL Statements now happens at compile rather than runtime.

4.2. Startup Times Comparison

Next, we’ll execute a script that starts each service, and at the same time, it starts trying to hit an endpoint that uses a repository. This way, we can monitor how long it took for the service to start, since the server and the repositories are ready for use.

For the repositories without AOT, the script output was:

==== RESULTS ====
time elapsed 10148 millis
Process Specific Memory/CPU (RSS KB / CPU Time): 289840 00:00:28

For the repositories with AOT:

==== RESULTS ====
time elapsed 9885 millis
Process Specific Memory/CPU (RSS KB / CPU Time): 291104 00:00:25

And for Spring Data AOT Repositories:

==== RESULTS ====
time elapsed 8745 millis
Process Specific Memory/CPU (RSS KB / CPU Time): 292864 00:00:23

This makes perfect sense, since we know that AOT and AOT Repositories target the improvement of startup times. And this is clear even for small projects like ours.

The memory improvement that is advertised by Spring is not shown here, but it makes sense for our small project.

Note, when starting the application without AOT, we should notice a log saying: Starting Application. But when using AOT, it should say Starting AOT-processed Application.

4.3. Comparison Under Load

Our last test includes a script that sends some traffic to each implementation and compares the performance.

For the repositories without AOT, the script output was:

==== RESULTS ====
Total requests: 6688
Success (2xx): 6688
...
Avg duration (measured): 51.7629ms
...
Max memory utilised: 331888

For the repositories with AOT:

==== RESULTS ====
Total requests: 7664
Success (2xx): 7664
...
Avg duration (measured): 43.934ms
...
Max memory utilised: 334000

And for Spring Data AOT Repositories:

==== RESULTS ====
Total requests: 6673
Success (2xx): 6673
...
Avg duration (measured): 49.0766ms
...
Max memory utilised: 337948

The result doesn’t show the memory improvement that Spring advertises, but this could be impacted by the project sizes and the data store.

5. Conclusion

In this article, we explored the new feature of Spring Boot 4, Spring Data AOT Repositories. We used a simple UserRepository class to demonstrate how Spring Data Repository worked before and what changes exactly this new feature introduced. Finally, we compared the performance implications of using the Spring Data AOT Repositories.

As always, the source code of the examples can be found over on GitHub.

Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)
2 Comments
Oldest
Newest
Inline Feedbacks
View all comments