Skip to main content

Spring

Modular Monolith vs Microservices in 2026: A Java Decision Framework

Most monolith-vs-microservices articles produce a tidy threshold number that doesn't survive checking the source it's attributed to. This one uses the real, enforced module boundaries from the Spring Modulith companion app to work through an honest cost accounting, what team size actually predicts, and a concrete five-step extraction sequence — ending in a decision procedure instead of a number.

Spring Modulith 2.1: Enforcing Module Boundaries Inside a Spring Boot Monolith

A clean package diagram is a promise, not an enforcement mechanism. This post builds a real 4-module Spring Boot order-fulfillment app, breaks the boundary between two modules on purpose, watches ApplicationModules.verify() fail with a real stack trace, and shows why the fix most people reach for first — routing through the public API instead of the internals — still fails, and why that matters more than the original mistake.

Debugging OutOfMemoryError: Heap Dumps, Eclipse MAT, and the Five Leak Patterns in Spring Apps

Five real Spring Boot apps, each driven to a genuine OutOfMemoryError under a constrained heap, each with a real .hprof dump read through Eclipse Memory Analyzer's headless batch report generator. Static caches, ThreadLocal, unremoved listeners, classloader leaks, and unbounded queues -- with the real console transcripts and MAT leak-suspect evidence for every one, plus what the JVM's own defaults quietly leave out when the crash happens in a container.

JVM Flags for Spring Boot in Containers (JDK 25/27): The Production Cheat Sheet

A flag-by-flag reference for running Spring Boot in containers on JDK 25 and JDK 27, measured in real Docker containers: how UseContainerSupport derives CPU count, collector and heap size from the cgroup, why MaxRAMPercentage fails safely while a hardcoded -Xmx gets the container SIGKILLed, the ActiveProcessorCount lie that inflates GC threads, native memory the heap percentage doesn't cover, and what JEP 523 and JEP 534 change by default on JDK 27.

Java Flight Recorder and Mission Control: Profiling a Live Spring Boot App in 20 Minutes

A hands-on guide to profiling a live Spring Boot app with Java Flight Recorder: real jcmd and jfr sessions finding a CPU hot method, allocation pressure and lock contention, a custom business event, and four traps that corrupt or hide data — a threshold that silently discards 12ms waits, a shared threshold between concurrent recordings, events lost to a missing try/finally, and a dump/stop bug that doubles every event.

Spring Kafka 3 to 4 Migration Guide

Moving a Spring application from Spring Kafka 3 to 4 looks like a version bump. It is three changes at once: the Kafka client itself jumps to 4.x, Spring Boot 4 stops configuring Kafka unless you use a new starter, and the JSON serializer you probably use is built on a Jackson that Boot 4 no longer puts on your classpath. This article migrates one small app and shows what each of those does when it goes wrong. You need to know what a Kafka topic, a producer and a consumer are. Everything else is explained as it appears. Versions tested. Before: Spring Boot 3.5.16, Spring Kafka 3.3.16, kafka-clients 3.9.2, JDK 21. After: Spring Boot 4.1.1, Spring Kafka 4.1.1 (latest GA), kafka-clients 4.2.1, JDK 25.0.4.1. Spring Kafka 4.2.0-M1 and M2 are milestones and were not tested. Date: 28 September 2026. Companion code: spring-messaging-demo/kafka4-migration.

Spring Batch 5 to 6 Migration Guide

Spring Batch 6 moves classes to new packages, changes what the Spring Boot starter gives you, and adds a second way to write a chunk step. Most of it fails loudly. One change does not: a listener that stops being called. This article migrates one small job from Batch 5 to Batch 6, one step at a time, and shows what each step prints. You should know what a batch job and step are. Everything else is explained on the way. If you are new to Batch itself, start with Spring Batch on Boot 4.1: jobs, steps, chunk processing and restartability. Versions tested. Before: Spring Boot 3.5.16 with Spring Batch 5.2.6 on JDK 21. After: Spring Boot 4.1.1 with Spring Batch 6.0.5, the latest GA, on JDK 25.0.4.1. Batch 6.1.0-M1 and 6.1.0-M2 exist as milestones and were not tested. Date: 28 September 2026. Companion code: spring-boot-demo/batch-5-to-6.

Gradle 9 for Spring Boot 4 Projects: Configuration Cache, Version Catalogs and Kotlin DSL

Gradle 9 removed several things that a typical Spring Boot 3 build script still uses, and it treats the configuration cache as the direction of travel. This article takes one small Spring Boot 4 project, written the way most Boot 3 projects were, runs it on Gradle 8 and Gradle 9, and fixes it step by step. Every error message below comes from a real run. You only need to have run ./gradlew build before. Terms such as configuration cache, version catalog and Kotlin DSL are explained where they first appear. Versions tested. Gradle 9.8.0 on JDK 25.0.4.1 and Gradle 8.14.3 on JDK 21, with Spring Boot 4.1.1, on 28 September 2026. Companion code: spring-boot-demo/gradle9.

Jakarta EE 11 for Spring Developers: What Actually Matters

If you write Spring for a living, “Jakarta EE 11” sounds like somebody else’s problem: application servers, EJBs, a different world. Yet every Spring Boot 4 application already runs on pieces of it — the servlet API under the web server, the persistence API under Hibernate, the validation API under @NotNull. When Jakarta EE 11 shipped, most of it arrived in your project without a headline. This article separates what actually changed in those pieces from what merely got a new number. It does that by reading the real API jars — EE 10 next to EE 11 — and Spring Boot’s own version list, rather than the marketing summary. You only need to know that Jakarta EE is a family of standard Java APIs and that Spring uses several of them. Versions and status. Spring Boot 4.1.1 (Spring Framework 7.0.9, Tomcat 11.0.24, Hibernate 7.4.5), JDK 25.0.4, Maven 3.9. Jakarta jars compared: Servlet 6.0.0→6.1.0, Persistence 3.1.0→3.2.0, Validation 3.0.0→3.1.0, Annotations 2.1.1→3.0.0, Concurrency 3.0.0→3.1.1, plus Data 1.0.2. Companion code: spring-boot-demo/jakarta-ee-11.