Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How Quarkus makes your apps cheaper, greener, a...

How Quarkus makes your apps cheaper, greener, and happier

Quarkus makes both people and hardware more efficient. That’s cool, but how does it work? Usually, we expect to trade-off developer experience against runtime efficiency. In this session, Holly will dive into some of the technical underpinnings of Quarkus’s efficiency. She’ll give advice for those using or considering Quarkus - should you be doing reactive programming? Do native binaries run fastest? The talk includes some theory (what underpins Quarkus’s surprising throughput?) and also live demos (does Quarkus really start faster than a light bulb? What does an integration testing flow with Quarkus look like?)

Avatar for Holly Cummins

Holly Cummins

November 11, 2025
Tweet

More Decks by Holly Cummins

Other Decks in Programming

Transcript

  1. how quarkus makes development faster greener happier Holly Cummins Senior

    Principal Software Engineer, Quarkus London Java Community November 11, 2025 https://bsky.app/profile/hollycummins.com
  2. how quarkus makes development faster greener happier cheaper Holly Cummins

    Senior Principal Software Engineer, Quarkus London Java Community November 11, 2025 https://bsky.app/profile/hollycummins.com
  3. @holly_cummins #Quarkus #IBM #RedHat “I can’t bring up the microservices

    in my Java dev stack … on my brand new Apple laptop with a M1 chip and 64GB of RAM.” - fintech CTO
  4. @holly_cummins #Quarkus #IBM #RedHat in production, it’s worse example microservices

    maths: airline maintenance scheduling system single service: ½ core + 1 GB RAM
  5. @holly_cummins #Quarkus #IBM #RedHat in production, it’s worse example microservices

    maths: airline maintenance scheduling system single service: ½ core + 1 GB RAM HA → 3x instances
  6. @holly_cummins #Quarkus #IBM #RedHat in production, it’s worse example microservices

    maths: airline maintenance scheduling system single service: ½ core + 1 GB RAM HA → 3x instances ~100 microservices
  7. @holly_cummins #Quarkus #IBM #RedHat in production, it’s worse example microservices

    maths: airline maintenance scheduling system single service: ½ core + 1 GB RAM HA → 3x instances ~100 microservices = 150 cores + 300 GB RAM
  8. @holly_cummins #Quarkus #IBM #RedHat why is this happening? mismatch between

    what we need and what the platform is optimised for
  9. @holly_cummins #Quarkus #IBM #RedHat Container platform machine node.js node.js node.js

    node.js node.js node.js node.js machine go go go go go go go go go go go go go go
  10. @holly_cummins #Quarkus #IBM #RedHat Container platform machine HotSpot Heap HotSpot

    Heap HotSpot Heap HotSpot Heap machine node.js node.js node.js node.js node.js node.js node.js machine go go go go go go go go go go go go go go
  11. @holly_cummins #Quarkus #IBM #RedHat traditional cloud-native java stack traditional cloud-native

    java stack traditional cloud-native java stack traditional cloud-native java stack node.js node.js node.js node.js node.js node.js node.js go go machine go go go go go go go go go go go go go go go go go go go quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus spoiler: we made stuff better :) container orchestration machine machine machine https:/ /developers.redhat.com/blog/2017/03/14/java-inside-docker/
  12. @holly_cummins #Quarkus #IBM #RedHat machine quarkus quarkus quarkus quarkus quarkus

    quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus container orchestration machine traditional cloud-native java stack traditional cloud-native java stack traditional cloud-native java stack traditional cloud-native java stack … a lot better quarkus native
  13. @holly_cummins #Quarkus #IBM #RedHat machine quarkus quarkus quarkus quarkus quarkus

    quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus quarkus container orchestration machine traditional cloud-native java stack traditional cloud-native java stack traditional cloud-native java stack traditional cloud-native java stack … a lot better quarkus native (but quarkus on jvm is also way smaller than traditional java)
  14. quarkus applications start fast quarkus + graalvm 0.014 Seconds rest

    application quarkus + open jdk 0.75 Seconds traditional cloud-native stack 4.3 Seconds https://quarkus.io/blog/runtime-performance/
  15. ok but does startup time matter? fast boot time means

    auto-scaling works better more resilience to load spikes
  16. quarkus + GraalVM 13 MB quarkus + OpenJDK 74 MB

    traditional cloud-native Stack 140 MB rest application https://quarkus.io/blog/runtime-performance/ quarkus improves memory utilization
  17. #Quarkus @holly_cummins hey, wanna see quarkus? hey, wanna see quarkus?

    hey, wanna see quarkus? hey, wanna see quarkus? hey, wanna see quarkus?
  18. #Quarkus @holly_cummins hey, wanna see quarkus? hey, wanna see quarkus?

    hey, wanna see quarkus? hey, wanna see quarkus? hey, wanna see quarkus? uhh … are you supposed to shut down applications after using them?
  19. #Quarkus @holly_cummins hey, wanna see quarkus? hey, wanna see quarkus?

    hey, wanna see quarkus? hey, wanna see quarkus? hey, wanna see quarkus? uhh … are you supposed to shut down applications after using them? 120 instances (!)
  20. @holly_cummins #Quarkus #IBM #RedHat remember the airline scheduling application? “[With

    Quarkus], we can run 3 times denser deployments without sacrificing availability and response times of services. ” – Thorsten Pohl
  21. let’s talk about throughput. quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper a

    trade-off of throughput against footprint 48 concurrent connections Traditional cloud native stack 3555 req/s
  22. but … traditional cloud native stack 3555 req/s quarkus native

    3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper a trade-off of throughput against footprint 48 concurrent connections
  23. but … traditional cloud native stack 3555 req/s quarkus on

    jvm 6389 req/s quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper a trade-off of throughput against footprint 48 concurrent connections
  24. but … traditional cloud native stack 3555 req/s quarkus on

    jvm 6389 req/s quarkus native 3212 req/s https://www.redhat.com/en/resources/mi-quarkus-lab-validation-idc-analyst-paper no trade-off, just better :) a trade-off of throughput against footprint 48 concurrent connections
  25. @holly_cummins #Quarkus #IBM #RedHat the two ways of improving performance

    •trade off one thing against another •eliminate waste
  26. @holly_cummins #Quarkus #IBM #RedHat how does a java framework start?

    packaging (maven, gradle…) build time runtime
  27. @holly_cummins #Quarkus #IBM #RedHat how does a java framework start?

    </> build time runtime load and parse • config files • properties • yaml • xml • etc.
  28. @holly_cummins #Quarkus #IBM #RedHat how does a java framework start?

    @ @ </> build time runtime • classpath scanning and annotation discovery • attempt to load class to enable/disable features
  29. @holly_cummins #Quarkus #IBM #RedHat how does a java framework start?

    @ @ </> build time runtime build a metamodel of the world
  30. @holly_cummins #Quarkus #IBM #RedHat how does a java framework start?

    @ @ </> build time runtime start • thread pools • I/O • etc.
  31. @holly_cummins #Quarkus #IBM #RedHat how does a java framework start?

    @ @ </> build time runtime ready to do work!
  32. @holly_cummins #Quarkus #IBM #RedHat what if we start the application

    more than once? @ @ </> @ @ </> @ @ </> @ @ </>
  33. @holly_cummins #Quarkus #IBM #RedHat what if we start the application

    more than once? @ @ </> @ @ </> @ @ </> @ @ </>
  34. @holly_cummins #Quarkus #IBM #RedHat what if we start the application

    more than once? @ @ </> @ @ </> @ @ </> @ @ </> so much work gets redone every time
  35. @holly_cummins JVM spends time loading classes for specific databases JVM

    class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database footprint example: Hibernate
  36. @holly_cummins JVM spends time loading classes for specific databases JVM

    class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database class for unused database turns out they’re never used footprint example: Hibernate
  37. @holly_cummins JVM spends time loading classes for specific databases JVM

    turns out they’re never used JIT spends time unloading classes footprint example: Hibernate
  38. @holly_cummins Hibernate example: ~500 classes which are only useful if

    you're running an Oracle database loaded and then unloaded
  39. @holly_cummins Hibernate example: ~500 classes which are only useful if

    you're running an Oracle database loaded and then unloaded every single start.
  40. @holly_cummins unused implementation the one we want interface unused implementation

    unused implementation the true cost of loaded classes isn’t just memory + start time method dispatching:
  41. @holly_cummins unused implementation the one we want interface unused implementation

    unused implementation the true cost of loaded classes isn’t just memory + start time method dispatching:
  42. @holly_cummins unused implementation the one we want interface megamorphic call

    slow dispatching unused implementation unused implementation the true cost of loaded classes isn’t just memory + start time method dispatching:
  43. @holly_cummins the true cost of loaded classes isn’t just memory

    + start time the one we want monomorphic call fast dispatching interface
  44. @holly_cummins #Quarkus #IBM #RedHat @ @ </> build time runtime

    start • thread pools • I/O • etc. what if we initialize at build time?
  45. @holly_cummins #Quarkus #IBM #RedHat @ @ </> build time runtime

    ready to do work! start • thread pools • I/O • etc. what if we initialize at build time?
  46. ok but we don’t need native quarkus is faster and

    smaller than legacy frameworks, even running on the jvm
  47. @holly_cummins doing more up-front - speeds up start - shrinks

    memory footprint - improves throughput (!)
  48. @holly_cummins #Quarkus #IBM #RedHat tests are run on every code

    change “reverse code coverage” means only relevant tests run mvn quarkus:dev continuous testing
  49. @holly_cummins #Quarkus #IBM #RedHat testcontainers integration … without quarkus @TestConfiguration(proxyBeanMethods

    = false) public class ContainersConfig { @Bean @ServiceConnection public PostgreSQLContainer<?> postgres() { return new PostgreSQLContainer<>(DockerImageName.parse("postgres:14")); } } public class TestApplication { public static void main(String[] args) { SpringApplication .from(MySpringDataApplication::main) .with(ContainersConfig.class) .run(args); } } @Import(ContainersConfig.class)
  50. @holly_cummins #Quarkus #IBM #RedHat zero-config testcontainers integration the only thing

    you need to do to make testcontainers work is not configure anything # configure your datasource quarkus.datasource.db-kind = postgresql quarkus.datasource.username = sarah quarkus.datasource.password = connor quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/mydatabase # drop and create the database at startup quarkus.hibernate-orm.database.generation = drop-and-create
  51. @holly_cummins #Quarkus #IBM #RedHat zero-config testcontainers integration the only thing

    you need to do to make testcontainers work is not configure anything # drop and create the database at startup quarkus.hibernate-orm.database.generation = drop-and-create
  52. @holly_cummins #Quarkus #IBM #RedHat zero-config testcontainers integration the only thing

    you need to do to make testcontainers work is not configure anything
  53. @holly_cummins #Quarkus #IBM #RedHat zero-config testcontainers integration the only thing

    you need to do to make testcontainers work is not configure anything quarkus also auto-invokes flyway and liquibase
  54. @holly_cummins #Quarkus #IBM #RedHat @ApplicationScoped public class GreetingRepository { public

    Entity findByName(int name) { return find("name", name).firstResult(); } void persist(Entity entity) {} void delete(Entity entity) {} Entity findById(Id id) {} List<Entity> list(String query, Sort sort, Object... params) { return null; } Stream<Entity> stream(String query, Object... params) { return null; } long count() { return 0; } long count(String query, Object... params) { return 0; } } example: panache + hibernate
  55. @holly_cummins #Quarkus #IBM #RedHat example: panache + hibernate @ApplicationScoped public

    class GreetingRepository implements PanacheRepository<Greeting> { public Entity findByName(int name) { return find("name", name).firstResult(); } }
  56. @holly_cummins #Quarkus #IBM #RedHat DAO example: panache + hibernate @ApplicationScoped

    public class GreetingRepository implements PanacheRepository<Greeting> { public Entity findByName(int name) { return find("name", name).firstResult(); } } repository pattern
  57. @holly_cummins #Quarkus #IBM #RedHat example: panache + hibernate active record

    pattern @Entity public class Greeting extends PanacheEntity { public String name; public LocalDate issued; @Version public int version; public static List<Greeting> getTodaysGreetings() { return list("date", LocalDate.now()); } }
  58. @holly_cummins #Quarkus #IBM #RedHat ok but i don’t like magic

    enrichment happens at build time no performance drag
  59. doing more up-front enables better devex runtime build time we

    can do cool code introspections here that would be too expensive and annoying to do at runtime @ @ </>
  60. @holly_cummins #Quarkus #IBM #RedHat the old ways all still work

    but you don’t have to type all the stuff unless you want to ok but i still don’t like magic
  61. @holly_cummins #Quarkus #IBM #RedHat <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-spring-web</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId>

    <artifactId>quarkus-spring-data-jpa</artifactId> </dependency> ok but we use spring option 1: compatibility libraries option 2: migration tooling • konveyor • open rewrite
  62. @holly_cummins #Quarkus #IBM #RedHat “After a week of development with

    quarkus, I was able to regain the same level of productivity as when I was developing with Spring Boot.” – Fawaz Paraïso, Decathlon
  63. @holly_cummins #RedHat density Source: Clement Escoffier experiment 1: cloud Setup:

    • 800 requests/second, over 20 days • SLA > 99% • AWS instances Assumptions: • Costs are for us-east-1 data centre
  64. @holly_cummins #RedHat Setup: • 800 requests/second, over 20 days •

    SLA > 99% Assumptions: Source: Clement Escoffier x Teads cloud carbon impact of framework choice interpolated carbon metrics
  65. @holly_cummins #RedHat Setup: • 800 requests/second, over 20 days •

    SLA > 99% Assumptions: Source: Clement Escoffier x Teads cloud carbon impact of framework choice the carbon is lower because the cost is lower interpolated carbon metrics
  66. @holly_cummins #RedHat Setup: • REST + CRUD • large heap

    • RAPL energy measurement • multiple instances to support high load
 Assumptions: • US energy mix Source: John O’Hara experiment 2: RAPL measurements
  67. @holly_cummins #RedHat Setup: • REST + CRUD • large heap

    • RAPL energy measurement • multiple instances to support high load
 Assumptions: • US energy mix Source: John O’Hara experiment 2: RAPL measurements quarkus on JVM has the lowest carbon … because it has the highest throughput
  68. • quarkus cuts carbon by ~2-3x* • native consumes more

    carbon than JVM (but it’s great for serverless scenarios!) carbon measurements: conclusions
  69. @holly_cummins #Quarkus #IBM #RedHat we need to make it a

    profession where “happy” is also a compliment
  70. @holly_cummins #Quarkus #IBM #RedHat tl;dpa (too long didn’t pay attention)

    deployment density lower cloud bill frictionless development experience Medium Nano auto-provision services zero-config live coding continuous testing developer UI greener happy, productive people