Spring to Quarkus: Move Your Java Code Seamlessly
Retain familiar annotations while exploring new growth paths for cloud-native development
If you're experienced with Spring Boot but are looking for something faster, leaner, and more cloud-native, Quarkus is a great option. The best part? You don’t need to start from scratch; Quarkus provides direct support for many Spring annotations, letting you reuse a large portion of your existing code.
This guide will show how you can bring your Spring Boot expertise into Quarkus, discuss key differences, and highlight areas where Quarkus can take your application beyond what’s possible in Spring.
Setting Up a Quarkus Project with Spring APIs
To get started, you can quickly generate a Quarkus project with Spring support using the Quarkus CLI:
quarkus create app com.example:spring-quarkus-demo \
--extension=spring-web,spring-di,spring-data-jpa,jdbc-postgresql,hibernate-orm-panache
This sets up a project supporting Spring-style web controllers, dependency injection, and JPA repositories.
Spring to Quarkus: Similarities and Differences
1. Dependency Injection
Both Spring and Quarkus use annotations for dependency injection, and Quarkus supports the most commonly used ones like @Autowired
, @Service
, @Component
, and @Repository
.
Spring Example
@Service
public class GreetingService {
public String greet(String name) {
return "Hello, " + name + "!";
}
}
Quarkus Equivalent
@Service
public class GreetingService {
public String greet(String name) {
return "Hello, " + name + "!";
}
}
Key Differences
While Spring Boot uses its
ApplicationContext
, Quarkus uses CDI (Contexts and Dependency Injection), which is lightweight and optimized at build time.@Autowired
is supported, but Quarkus prefers constructor injection to align with best practices.
2. REST Controllers
Quarkus supports Spring MVC annotations, so a Spring Boot @RestController
works out of the box.
Spring Example
@RestController
public class GreetingController {
@Autowired
GreetingService greetingService;
@GetMapping("/greet/{name}")
public String greet(@PathVariable String name) {
return greetingService.greet(name);
}
}
Quarkus Equivalent
@RestController
public class GreetingController {
@Autowired
GreetingService greetingService;
@GetMapping("/greet/{name}")
public String greet(@PathVariable String name) {
return greetingService.greet(name);
}
}
Key Differences
Spring uses Spring MVC, whereas Quarkus also offers JAX-RS (RESTEasy) as a more native, faster alternative.
Spring’s
@RequestMapping
is supported, but Quarkus developers often migrate to Jakarta REST annotations (@Path
,@GET
,@POST
) for better efficiency.
3. Database Access (Spring Data JPA in Quarkus)
Quarkus supports JpaRepository
, allowing Spring Data JPA repositories to work seamlessly.
Spring Example
public interface PersonRepository extends JpaRepository<Person, Long> {
List<Person> findByName(String name);
}
Quarkus Equivalent
public interface PersonRepository extends JpaRepository<Person, Long> {
List<Person> findByName(String name);
}
Key Differences
Quarkus compiles JPA models at build time, reducing runtime overhead.
Hibernate Panache (Quarkus-native alternative) provides an active record pattern, making data access more streamlined.
A Realistic Migration Scenario
Imagine a company running a Spring Boot monolith that handles user management, order processing, and reporting. The team wants to move to containerized microservices but is facing long startup times and high memory usage.
Phase 1: Initial Migration
Convert the existing Spring Boot app to Quarkus using Spring extensions (
spring-web
,spring-di
,spring-data-jpa
).Test if everything works in JVM mode first before moving to native mode.
Keep using familiar annotations like
@RestController
,@Autowired
, and@Repository
to minimize changes.
Phase 2: Optimizing for Quarkus
Replace
@RestController
with JAX-RS (@Path
,@GET
) to benefit from faster boot times and lower memory usage.Move from Spring Data JPA to Hibernate Panache, which simplifies repository methods.
Example of Hibernate Panache (Quarkus-native alternative):
Instead of:
@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {
List<Person> findByName(String name);
}
You can write:
@Entity
public class Person extends PanacheEntity {
public String name;
public static List<Person> findByName(String name) {
return find("name", name).list();
}
}
This removes the need for a repository interface altogether.
Phase 3: Cloud-Native Evolution
Use Quarkus Dev Services to automatically start PostgreSQL and Kafka in dev mode—no manual Docker setup required.
Deploy as GraalVM-native executables for near-instant startup times and minimal memory footprint.
Integrate Quarkus Funqy for multi-cloud serverless deployment, something Spring doesn’t offer.
Where Quarkus Provides More Than Spring
Compared to Spring Boot, which typically starts in a matter of seconds, Quarkus running on the JVM can start in under a second, and Quarkus in native mode launches in just a few milliseconds. Spring Boot tends to use more memory, while Quarkus on the JVM typically consumes 30–50% less; the native variant reduces memory usage even further. In terms of ORM, Spring relies on traditional JPA practices, whereas Quarkus offers an active record approach with Panache (JVM mode) and a fully optimized version for native deployment. Instead of Spring MVC, Quarkus relies on RESTEasy JAX-RS, which runs faster by default and can be compiled to native for even greater performance gains. On the cloud side, Spring Boot frequently requires Spring Cloud extensions for Kubernetes, while Quarkus is designed to be Kubernetes-native right out of the box. For serverless, Spring-based AWS Lambdas experience slower cold starts, but Quarkus on the JVM can improve startup times significantly, and the native mode can drop cold starts to a near-instant response.
Final Thoughts: When to Go Beyond Spring Compatibility
While Quarkus makes migration easy by supporting Spring APIs, fully embracing Quarkus brings even greater benefits:
Faster boot times and less memory usage when replacing
@RestController
with JAX-RSPanache ORM simplifies entity management
Dev Services eliminates config headaches in local development
Native compilation makes apps ideal for Kubernetes and serverless
If you're starting with Quarkus today, you don’t need to rewrite everything at once. Migrate step by step, keeping your existing Spring skills while gradually shifting towards Quarkus-native optimizations.
Give it a shot - you might never look back.