Bulkheads in Spring Boot: Stop One Slow Dependency From Sinking the Service

A ship stays afloat when one compartment floods because bulkheads — the watertight walls between sections — keep the water in one place. Your service has the same problem in reverse: one slow dependency floods the shared thread pool, and everything else drowns with it. A payment provider that takes 2 seconds instead of 200 milliseconds doesn’t just make payments slow. It occupies every request thread until the pool is full, and then your health endpoint, your login page, and your fast internal calls all queue behind it. The service isn’t broken. It’s busy — on someone else’s problem. ...

2026-11-08 · 12 min · Ramesh

Solve Every Error Once: The Fleet Playbook for Migrating 60+ Services to Spring Boot 4

Migrating one service to Spring Boot 4 is a weekend project. Migrating sixty is a program — and programs fail in a specific way: every team independently rediscovers the same seven errors, burns a week each, and the “migration” becomes sixty snowflake upgrades with sixty subtly different outcomes. The fix is a discipline with an unfriendly name and a friendly result: solve every error once. When a team hits a migration error, the output isn’t a fixed service — it’s a permanent, automated fix that no other team ever has to think about again. Here’s the playbook. ...

2026-10-18 · 8 min · Ramesh

Dead Letter Queues: Where Your Poison Messages Actually Go

Every message-driven system eventually meets its poison message: one malformed payload, one downstream bug, one record that will never process successfully — retried forever, burning CPU, and in the worst designs blocking every message queued behind it. The dead letter queue is the answer, but “just add a DLQ” hides three decisions: how many attempts before giving up, what counts as an attempt, and who gets woken up when something lands in the DLQ. Get any of them wrong and the DLQ is theater. ...

2026-10-14 · 9 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

Declarative HTTP Clients in Spring Boot 4: Moving Beyond RestTemplate

Every Spring codebase has one: the PaymentsClient class. Sixty lines of restTemplate.exchange() with string-concatenated URLs, an HttpEntity built by hand for every POST, a try/catch that maps HttpStatusCodeException to something the caller understands, and a custom ResponseErrorHandler someone wrote in 2021 that nobody dares to touch. It works. But the platform is moving on, and there are now two modernization paths worth knowing. The first is the modern imperative successor: Spring Framework 7 deprecates RestTemplate in favor of RestClient — new imperative clients should generally prefer RestClient, while existing working RestTemplate code doesn’t require a flag-day rewrite. The second is the declarative HTTP client: an interface, some annotations, and no handwritten implementation class. It is not a replacement for RestClient — it is an interface/proxy abstraction that sits on top of an underlying HTTP client: ...

2026-10-01 · 15 min · Ramesh