Java 25 · Spring Boot 4 · an idea still taking shape

What if we needed fewer frameworks?

A thought on dependencies, Spring Boot, and what Java 25 already gives us

We've gotten really good at adding libraries. I've started to wonder whether the next improvement might be removing a few – without making the system dumber, riskier, or harder to operate. This is a line of reasoning, not a conclusion.

Fewer dependencies?More plain JavaSpring where it earns its keepLess to maintain
Abstract visualization of many technical layers being pared back toward a simple core.

For years, Java development has often meant reaching for a framework or library the moment a new need appears. That's been rational, and I've done the same. But the Java platform has grown, the language has gotten better, and the cost of writing mechanical code by hand has dropped. So I've started turning over a question I don't have a finished answer to: how much of what we usually add do we still actually need?

01 · The idea

This isn't about Spring being the problem

Spring Boot solves a lot of hard problems, and it solves them well. For public APIs, security, advanced routing, observability, and large integration surfaces, Spring is probably still the cheapest option overall.

But Spring has become such a default reach that I suspect we sometimes grab it even when the problem is smaller than the solution. That's the suspicion I want to examine here.

A small internal service might need only a handful of HTTP calls, a database, one outgoing call, and some business logic. Java 25 already has an HTTP client, JDBC, scheduling, records, logging, JFR/JMX, and modern concurrency tools. Virtual threads also make plain, blocking code considerably more attractive for I/O than it was a few years ago.

Java hasn't become a new Spring. But maybe the line for what actually needs a framework has shifted a little?
Abstract network diagram where a clear core connects to a limited number of outer systems.
A goal I find appealing: a clear core and a small number of deliberate boundaries toward the outside world.

02 · The maintenance surface

Maybe dependencies are a bit of an iceberg

When we look at a pom.xml or build.gradle, we only see part of the system's technical surface. Underneath it sit transitive libraries, version couplings, autoconfiguration, proxies, annotation processing, and conventions that someone has to understand the day something breaks.

Counting JAR files therefore feels like a blunt measure. A small external dependency can be very cheap. Four hundred lines of hand-rolled OAuth code can be very expensive.

So by minimalism I don't mean the least code, or zero libraries. Rather, less unnecessary semantics – less technology the team has to carry over time.

Iceberg where a small visible tip represents direct dependencies and a much larger structure below the surface represents the hidden maintenance surface.
Direct dependencies are the visible part. My sense is that maintenance cost usually sits in everything that comes along with them.
VersionsUpgrades, compatibility, and coordination.
SecurityCVEs, parser and network surface, patch work.
SemanticsHidden rules, proxy behavior, and lifecycle.
ChangeHow much needs to be understood next time requirements shift?

03 · A proposed order

What if we asked in this order?

Instead of starting with "which library should replace this?", you could work through four steps. The further right we get, the more specialized semantics we choose to let someone else own. The order isn't a truth – mostly a way to make the choice deliberate.

1. Is it needed at all?Is the behavior needed in the first place? A cache or internal event bus that never gets built has no implementation to maintain.
2. Is it in the JDK?Is there a direct, sufficient solution in Java 25? For example an HTTP client, files, Base64, scheduling.
3. Does a bit of our own code suffice?Is the semantics simple and local? Mapping, configuration, a small retry loop, or a composition root can turn out to be fairly clear, ordinary Java.
4. Let the specialist handle itIs it about JSON, OAuth/OIDC, connection pooling, broker protocols, or advanced telemetry? Then I think a mature library is almost always cheaper.

04 · Where Spring might fit best

What if Spring lived at the edge?

The idea I personally find most interesting isn't about removing Spring Boot. It's about maybe no longer letting Spring be the application's primary programming model.

My thinking is that if the core is free of Spring, the next decision becomes less dramatic. A complex service can happily stay on trimmed-down Boot. A small internal service could later move further toward plain JDK. A batch job or worker might never have needed Spring in the first place. But that's just a thought – I don't know how well it holds up in your systems.

05 · A few things I'm curious about

Not everything probably needs the same treatment

Maybe simpler today

Lombok and mappers

Records and explicit code mean some of the mechanical help feels less valuable than it used to.

JDK is often enough

Outbound HTTP

The JDK HttpClient seems to go a long way for ordinary service-to-service communication.

Depends on the service

Spring DI

Constructor injection needs no container. At the same time, a large and dynamic object graph can very well justify Spring.

Worth a look

JPA / Hibernate

For clear SQL and a limited model, JDBC can be simpler. For rich object graphs, an ORM is probably still cheaper.

I'd keep this here

JSON and security

General-purpose JSON parsing and OAuth/OIDC carry difficult semantics that should rarely become in-house infrastructure.

I'd keep this here

Connection pool

JDBC comes with the JDK, but a production-grade pool doesn't. HikariCP feels like an obvious dependency to keep.

06 · What would we gain?

If it holds, it's about maintenance cost

What would make this idea worth anything isn't a tidier dependency tree. It's whether, over several years, the team ends up with less technology to coordinate, fewer layers to understand, and less impact when the platform is upgraded. And that's of course an assumption that needs to be tested.

If we reduce…We might gain…But only if…
External dependency familiesFewer separate version and upgrade tracksWe don't replace them with large in-house frameworks
Spring types in the domainLess impact from framework upgrades and simpler testsThe boundaries between core and adapters stay clear
Runtime magicMore visible control flow and easier debuggingThe explicit code stays small and understandable
Excessive standardization in codeLess local infrastructureThe organization still standardizes important contracts and operational behavior

07 · One thing that may have changed

More code can sometimes mean a smaller system

AI makes it cheaper to produce mechanical mappers, JDBC row mappers, config records, adapters, tests, and repetitive decorators. If that's true, it lowers the value of abstractions whose main contribution is that we get to skip writing a few lines.

At the same time, AI hardly makes protocols, cryptography, parser edge cases, concurrency, or transaction semantics any less dangerous. It's quick to generate a connection pool. That doesn't mean the team should own one.

A bit more visible code could add up to a considerably smaller system.

08 · Where I've landed so far

Maybe minimalism is mostly about choosing responsibility

I don't see the point in making "zero Spring" a creed. But I do think there's something to making every dependency a deliberate choice.

A small service might get by on the JDK's HTTP server. A complex public-facing service can happily stay on WebMVC and Spring Security. A worker might end up being nearly plain Java. What they'd have in common is that the business logic gets to be ordinary Java, and specialist libraries are kept at clear boundaries.

Ask first whether it's needed. Then check the JDK. Write small, concrete code when the semantics are your own. And let specialist libraries take on what belongs to a hard protocol, a security standard, or a resource manager.
This is an idea I'd like to keep thinking through together with others – not a migration recipe. I'm fully prepared for it to hold up worse in reality than on paper. The question I find interesting isn't "can we remove Spring?", but "which technology actually gives the lowest total cost of ownership for this particular service?" If you've seen evidence pointing the other way, I'd genuinely like to hear it.