Structured Concurrency in Java: What Virtual Threads Didn't Fix (JEP 533, JDK 27)

Virtual threads (final since JDK 21) made blocking I/O cheap. But cheap threads didn’t fix the hard part: when you fan out to five subtasks and one fails, who cancels the other four? With ExecutorService + Future, the answer is “you, manually, and you’ll get it wrong.” That failure mode — leaked threads, swallowed errors, unobserved work — is what structured concurrency exists to kill. One warning before the code: this API is still moving. Everything below is verified against JEP 533, the seventh preview, targeting JDK 27 — and most blog examples you’ll find online show the obsolete API. Get the status table right first, then the code. ...

2026-10-08 · 8 min · Ramesh

Externalized Configuration in Spring Boot 4: Change a Property Without Restarting the Service

It’s 3 AM and the payment provider is timing out. The fix is one property: raise payments.timeout from 5s to 15s until their incident clears. But that property lives in application.yml, baked into the jar, deployed to twelve instances. So you rebuild, push, and roll twelve restarts — for a value that isn’t code. Externalized configuration is the pattern that ends this ritual: configuration lives outside the deployable artifact, in one versioned place, and services pick it up at startup — or at runtime, without restarting. Spring Cloud Config is the canonical Spring implementation, and it pairs with the config-data import that replaced the old bootstrap.yml setup back in Boot 2.4. ...

2026-10-07 · 10 min · Ramesh

Circuit Breakers in Spring Boot: Resilience4j, Done Right

Your checkout service calls the payment gateway. One night the gateway has a bad deploy and starts timing out. Every synchronous checkout request thread now remains occupied for the full 10-second client timeout. Threads pile up, the pool exhausts, health checks fail, and the load balancer starts draining your perfectly healthy checkout pods. Nothing about checkout is broken — it just never stopped calling a dependency that was already dead. ...

2026-09-30 · 14 min · Ramesh

After the Outbox: The Saga Pattern for Multi-Service Transactions in Spring Boot

It’s 3 AM again. A customer placed an order, payment went through, and inventory reservation failed — the warehouse is out of stock. The customer has been charged for something that will never ship. The order row exists and the customer was charged, but nothing will ship — and no single transaction can unwind it, because there is no @Transactional that spans your order service, your payment service, and your inventory service. Each one already committed its own local transaction. ...

2026-09-29 · 11 min · Ramesh

Dual Writes Are Lies: The Transactional Outbox Pattern in Spring Boot + Kafka

It’s 3 AM. A customer paid, the orders row is in your database, and the OrderCreated event never reached Kafka. The warehouse never shipped. The email never sent. Somewhere in your service there is code that looks like this: @Transactional public Order placeOrder(PlaceOrder cmd) { Order order = orderRepository.save(new Order(cmd)); // write #1 kafkaTemplate.send("orders", order.getId(), toJson(order)); // write #2 — outside the safety net return order; } Two writes. No shared atomicity. If the broker is down, if the pod gets killed, if the send times out after the commit — the database and the downstream world silently disagree, and you get to find out from an angry customer. This is the dual-write problem, and the fix is the transactional outbox pattern. ...

2026-09-27 · 7 min · Ramesh