alt.hn

3/26/2026 at 6:29:56 PM

Spring Boot Done Right: Lessons from a 400-Module Codebase

https://medium.com/all-things-software/spring-boot-done-right-lessons-from-a-400-module-codebase-e636c3c34149

by dknj

3/30/2026 at 2:25:48 PM

I worked on a core Spring Boot project for five or six years at a very large enterprise. In my opinion, the most dangerous thing about this framework is that it makes its core users feel far too self-assured.

When looking at problems, your mind becomes consumed with how to force everything into design patterns—like architectural separation, DI, or interface / implementation split. This causes developers to lose sight of the actual essence of the problem because they are obsessed with conforming to the framework.

Because the ecosystem and toolchain surrounding Spring Boot and Java are so mature and well-supported, it is very easy to find community tools that make you feel like you are doing things the "right way."

I only realized these issues after I left Spring Boot and Java development behind. Now, I much prefer using TypeScript or Python to write code (for example, web servers).

I also prefer using various SaaS solutions to handle authentication and user registration rather than rebuilding it all myself with Spring Boot Security. I honestly never want to go back to the days of writing Java again.

by e7h4nz

3/30/2026 at 3:13:48 PM

Funny how that works - I started with Spring both before and after Boot as well as some Scala.

I wouldn’t trade Java / Spring for the world. It forces a coherence, perhaps not perfectly, but it provides guidelines to follow.

I’ve been stuck in Node / TypeScript / Microservice hell for most of the last 15 years and I couldn’t hate it more. The open-source ecosystem is extremely lacking, even now, on something like a good XML library. I think we’ve got four different ones installed in our core platform each handling different needs (traversal, generation, manipulation, validation).

On top of it all, since there isn’t “one way” we’ve got several dozen micro services. There isn’t a single bit of consistency other than “Express.” Logging, authentication, routing, validation - it’s all completely up in the air. It robs us all of efficiency from the lack of common language and pattern. We spend more time refreshing ourselves on any given project than doing feature work or bug fixes.

Madness!

by antonymoose

3/30/2026 at 3:23:57 PM

Removed microservices and RPC, keep all TypeScript codes in a single monorepo. Avoiding `any` and using ts-rest automatically keep types synchronized between the web and frontend applications.

This has made my life much easier.

by e7h4nz

3/30/2026 at 4:25:47 PM

I hear this a lot from a lot of my coworkers who like Java Spring - they trust Spring to do things right, more than themselves.

On the other hand, I hate Java Spring because I feel like I don't trust it - it doesn't let me look into and understand the internals easily, making me feel like I'm afloat on a pile of abstracts I'm not allowed to look down into.

Looking at some other projects enterprise js/ts codebases though, I see a lot of "I don't understand how this works so I'll try random things until it works". In that kind of environment, I can understand the attraction of Spring - it's not great, but it also won't be a flaming pile of unbaked abstractions.

by BariumBlue

3/30/2026 at 4:52:42 PM

Spring framework may look complicated only at start, until you get it, but then it becomes quite easy to reason about.

OTOH, Spring Boot is a huge pile of various loosely coupled framework connectors, web, queues, security, databases etc. Some of them are of good quality, some are not so good. It is that uneven mix giving the perception that Spring is a mess.

by ivan_gammel

3/30/2026 at 5:01:35 PM

> it doesn't let me look into and understand the internals easily

what does this mean? you can single step into framework code

by nh23423fefe

3/30/2026 at 9:35:44 PM

Mostly just boils down to a Chain-of-Responsibility pattern which is incredibly easy to reason about. Just a way to compose functions.

As far as digging into internal, how often do you look into Express or Rails internals or any other? For me it’s a rare day to need to do so.

Only time I recall having to read Spring source code was when I used their Social Media Auth library sometime in the early 2010s when it was quite a primitive experience.

by antonymoose

3/30/2026 at 4:05:12 PM

I’ve Been stuck with Spring for many years too and I think it’s just awful choice for micro services that need to scale, simply due to startup time.

Not to defend Nodejs ecosystem - your points are 100% valid.

With that in mind, I think Go is much better option.

by ekropotin

3/30/2026 at 4:55:59 PM

Spring may be a bad choice for microservices (context required, because it is not true in general), but it is strange to compare it (DI framework/mvc/orm abstraction etc) with Go (programming language). Java exists in many flavors, you do not have to use Spring to build a performant microservice.

by ivan_gammel

3/30/2026 at 5:10:52 PM

Fair enough! Indeed, there are ways to build performant microservices on Java, e.g. Qwarkus + GraalVM, but I've never seen anyone in enterprise world is doing it - 99% of services are still being build on Spring Boot, so in my mind Java in SB are inseparable.

by ekropotin

3/30/2026 at 5:23:17 PM

That's kind of where I stand on this too... though I'm more fond of a lot of C# than Java, I find that it's the developer ecosystem and work environments themselves that exist on so many piles of abstractions and patterns that it's often hard to even grasp the meat of what's being done over the abstractions themselves.

I've trended towards feature oriented hierarchies over type of thing hierarchies as I find they tend to be simpler, easier to replace over time and often much easier to maintain than separating DAL/BLL/SVC/VM/M/V layers etc. I really don't mind if my endpoint file sits next to my database access file, next to my validation file along with the test files for all of them in a single directory for a given feature. The feature is the concern, not the fact that you have a web endpoint, or need to talk to a database.

They're also easier to manage in a monolith and break apart as needed without having to replicate the jungle for want of a banana.

by tracker1

3/30/2026 at 5:19:11 PM

I bet this is happening because in many enterprise applications you do not need high performance. Requirements to a service doing 1000 transactions a day are very different from requirements to a service doing HFT. Service per bounded context may be reasonable choice and Spring Boot/Spring Cloud may be adequate solution for it.

by ivan_gammel

3/30/2026 at 5:27:13 PM

I think this is probably a large part of it... I remember working on an app a few years ago, where it was explicit that it likely wouldn't see more than 15-20 active users at any given deployment... and with the level of normalization at the database layer, and literally 95% of the logic INSIDE the database (sprocs), it was just about falling over on a modest server trying to handle a dozen users.

Worse still, is the variance and onboarding for each customer was taking roughly twice as long as the previous one... I left during the dev cycle to bring in the 4th client. These were state/county agencies, each with slightly differing requirements. I was in charge of the UI and the API for the UI... putting all the logic inside the DB itself was emphatically NOT my decision.

by tracker1

3/30/2026 at 7:47:25 PM

> because in many enterprise applications you do not need high performance

Looking at and having looked at some of their cloud spend etc, nah.

To be more specific there's a lot of fat. Whether that's HFT style high performance is a different story.

by re-thc

3/30/2026 at 8:43:51 PM

You can drop cloud spending by 10x factor and still use Spring Boot comfortably. In startup world exist infra costs benchmarks and they are very generous. That fat does not come from frameworks, it comes from not spending an extra hour on solution design.

by ivan_gammel

3/30/2026 at 5:50:47 PM

Minecraft builds their servers using Micronaut! It's such a breath of fresh air compared to spring.

I've only ever had to debug spring DI once, I'll admit it usually works. But when it doesn't..... All those proxy objects will drive you nuts!

It's a very clever solution really.. And that's the problem! You don't want to build your servers on a clever foundation, you want a simple one!

by amarant

3/30/2026 at 4:11:54 PM

I agree. Whenever I've tried jumping into NodeJS world, I quickly get overwhelmed by the lack of obvious "right" solutions to common problems. There's no way to know which of the dozens of ORM's, auth libraries or whatever will be still around 10 years from now. With Java & Spring the choice is always obvious.

Of course there are "batteries included" frameworks for NodeJS too, but they all seem to be unstable compared to Spring Boot.

by reeredfdfdf

3/30/2026 at 5:34:19 PM

I tend to defer auth to JWT token usage... you have a properly RSA signed token against a valid public key, you're in.

In terms of ORMs, I actually avoid them... I like data adapters that make writing general SQL queries easier... for C# I tend to use Dapper... for JS/TS, I'll use a template string interpreter shim over the database adapter that returns Enumerable<T>?... very similar to my usage of Dapper.

Just about the simplest things that I can do to get things going, and generally in the simplest path forward. Today, generally speaking, hono, zod, openapi with a bit of hand-wiring as described above. At least for the backend, services, etc. With open-api configured, I can generate client adapters and relatively easily integrate with an OAuth provider of my choice (often AD/Entra in practice).

I will also usually create a self-signing JWT auth for dev/testing to make it easier to be "anyone" in any role for testing... where the release application is more restricted.

by tracker1

3/30/2026 at 2:42:51 PM

I like Java fine. I would probably prefer Ruby, Rust or LISP given the chance. But I can't disagree with anything you say. So many Java enterprise shops have absurd inheritance and "design pattern" abuse that makes it harder to actually work with the code, and slows things down.

by ecshafer

3/30/2026 at 5:36:34 PM

Similar for C# in practice... I actually really like a lot of modern C#, though I use FastEndpoints as an (imo) upgrade to minimal API surface, generally with Dapper and as few layers as possible in a feature oriented structure (single project as long as possible). I had to split off some logic into a separate shared library and worker service app from the api app on the server. Client is a React SPA.

by tracker1

3/30/2026 at 2:49:37 PM

[dead]

by e7h4nz

3/30/2026 at 5:35:36 PM

> I also prefer using various SaaS solutions to handle authentication and user registration rather than rebuilding it all myself with Spring Boot Security.

I'm confused. Spring Security does provide you ways to create your own auth layer. However, you can use your existing identity provider or any external provider (there are starters for many providers).

by microflash

3/30/2026 at 3:08:43 PM

Spring is such a massive framework and it definitely has parts that aren't, frankly, well done. More than once Spring has ultimately been the source of performance issues for us with the solution being to ditch spring and do things with just the JDK. A lot of those cases have been fixed, however, even in the best case spring will take something that could have been a single function call and turn it into a maze of 20 different function calls because it's handling all sorts of weird edge and corner cases that aren't applicable to your code. It also doesn't help that some things are simply bolted in which makes it even harder to understand what is going on under the covers.

It also doesn't help that it's really easy to end up bringing in the entire framework for what you assumed were single function portions of the framework.

That said, it's the framework you probably want to use if you are doing Java. Just not if you are doing fast java.

by cogman10

3/30/2026 at 3:26:09 PM

> I also prefer using various SaaS solutions to handle authentication and user registration rather than rebuilding it all myself with Spring Boot Security.

i haven't used Spring in a decade but even back then Spring Security had support for all kinds of federated authentication/authorization providers and standards.

by chasd00

3/30/2026 at 5:44:22 PM

Java is fine, but spring boot is an abomination. Give micronaut a go and see for yourself!

by amarant

3/30/2026 at 3:33:18 PM

Nothing about Spring forces you to use or engage in or use design patterns. If it does im pretty sure that's a plus. Juniors can have clear path towards being productive and feel quickly oriented.

Like sibling comment mentioned you can integrate anything with Spring Boot. Its a high productivity framework to accomplish alot. Your frustrations speak more to the job you took rather than the framework they forced you to use.

by smrtinsert

3/30/2026 at 1:55:17 PM

Ops person here who has supported Java/SpringBoot applications. I think most of dislike of Java apps comes not from language or framework BUT from fact that most Java using workspaces are filled with mediocracy. They tend to be businesses with products that have extreme moats and thus quality of software barely matters. I imagine most people who would even read this medium article are dreaming of better than that.

by stackskipton

3/30/2026 at 2:41:03 PM

I 100% agree. I have seen enterprise spring applications that throw away all of the speed through huge amounts of hot path object creation, nested loops, absurd amounts of factories, etc. After going through enough AbstractFactoryFactory calls to make object in an n^3 loop, the framework doesn't matter.

by ecshafer

3/30/2026 at 2:46:05 PM

There really is an unlimited potential for crappy code in the enterprise. I imagine the volume will increase drastically in the age of AI.

by switchbak

3/30/2026 at 2:51:07 PM

Usually languages are not the issue. It is the code that we write. As long as languages help us to find/debug a problem caused by crappy code - we should be good. Coding is kinda creative work. There is no standard to measure creativity or pitfalls of using wrong patterns. The incidents & RCAs usually find these. But most of the times it is already too late to fix core problem.

by the_arun

3/30/2026 at 5:47:46 PM

Not sure that I agree... I think some of the worst AI code I've had to deal with and the most problematic are when dealing with Java or C#... I've found TS/JS relatively nice and Rust in particular has been very nice in terms of getting output that "works" as long as function/testing is well defined in advance.

by tracker1

3/30/2026 at 5:34:05 PM

In my experience, the same enterprise developers will write complex abstractions in any language. If you have a million coders, 500k will by definition write below average code. And if some of them are elevated to tech leads in enterprise companies, they will spread their "style" to others.

by throwawey1234

3/30/2026 at 5:46:10 PM

This is definitely true... as a mod/admin on EchoJS, can't tell you the number of times I've seen unnecessary IoC/DI libraries created in JS/TS to match the style of Java or C#.

The reality is that as a scripted environment, there are provisions to override dependencies for testability.... so unless you literally need multiple implementations of a given adapter, you don't need a DI/IoC framework and adding one only detracts from your overall solution. I'm a strong believer in that abstractions should mostly serve to hide relative complexity to make the rest of the application easier to reason with.

I'm also a big fan of the first version of anything being done in a scripted language with an emphasis on correct behavior. JS/TS and Python are more adaptable earlier on without committing to Java/C# or even Rust or Go. I understand a desire for homogeny, but that often can hold you back from creating something functional and easy to replace first.

by tracker1

3/30/2026 at 4:32:36 PM

There are certain non-software industries that seem to have strong hiring preferences for workers who started in the industry over computer science chops, and a lot of those tend to use Java. For example, biotechs.

by evantbyrne

3/30/2026 at 4:47:59 PM

Because most of time, understanding the business logic is harder than writing to the code in these industries.

Java is default since it's what taught to many college graduates with added bonus that's taught to most college grads in Indian subcontinent so outsourcing is much easier.

by stackskipton

3/30/2026 at 5:41:15 PM

I think that's generally true of most knowledge domains for anything resembling complex work. Govt, banking, pharma, medical, SaaS all will have a lot of specific requirements that come from deep historical, regulatory or business needs.

I would suggest that the rise of Python is very similar, as it's common in education circles. It's not even that Java as a language is particularly bad, it's how it is used in practice. Though I really do favor C# over Java, there's a similar stigma that comes from the community itself, not the language or it's baseline abilities. And this is a valid criticism.

by tracker1

3/30/2026 at 6:40:46 PM

Getting up to speed on the business logic was arguably the easiest part of my last job where the product was a liquid biopsy. Regardless of industry, you have to learn how to communicate with stakeholders and collect requirements. The existing software being a mess was a much more significant challenge. They also had similar issues on the data science side, where I would argue they did not lean into modern ML nearly enough and instead opted to do the familiar thing.

by evantbyrne

3/30/2026 at 2:59:08 PM

Alternatively, I think of Java and Spring Boots as being incredibly valuable by letting companies that don't really have software as a core competency to make reasonably performant and structured applications.

Mediocrity will never not exist, and you unlock a lot of value by optimising for it.

by dukeyukey

3/30/2026 at 4:59:08 PM

Exactly. It allows to build boring stuff at a fraction of what a SV startup would burn using some fancier tech. And most problems in the world are boring stuff.

by ivan_gammel

3/30/2026 at 5:48:36 PM

There is no right way to do Spring Boot.The entire idea is broken.

Dependency injection is good. It makes it possible to test stuff.

Automagic wiring of dependencies based on annotations is bad and horrible.

If you want to do dependency injection, you should do it the way Go programs do it. Create the types you need in your main method and pass them into the constructors that need them.

When you write tests and you want to inject something else, then create something else and pass that in.

But the idea that you create magic containers and then decorate packages or classes or methods or fields somewhere and then stuff suddenly gets wired into something else via reflection magic is a maintenance nightmare. This is particularly true when some bean is missing, and the one guy who knows which random package out of hundreds has that bean in it is on vacation and the poor schmucks on his team have no clue why their stuff doesn't work.

"I added Spring Boot to our messy Java project."

"Now you have 3 problems."

by swisniewski

3/31/2026 at 3:59:35 PM

Manual dependency injection is fine, but it doesn't scale. Especially when you start refactoring things and dependencies need to be moved around.

The other issue is dynamic configuration. How do you handle replacing certain dependencies, e.g. for testing, or different runtime profiles? You could try to implement your own solution, but the more features you add, the closer you'd get to a custom DI framework. And then you'd have an actual mess, a naive non-standard solution for a solved problem, because you didn't want to read the manual for the standard implementation.

By the way, Spring dependency injection is mainly based on types. Annotations are not strictly necessary, you can interact with the Spring context in a procedural/functional manner, if you think that makes it better. You can also configure MVC (synchronous Servlet-based web) or Webflux (async web) routes functionally.

When a bean is missing, the app will fail to start, and you will get an error message explaning what's missing and which class depends on it. The easiest way to ensure this doesn't happen is to keep the empty @SpringBootTest test case that comes with the template. It doesn't have any assertions, but it will spin up a full Spring context, and fail if there is a configuration problem.

The only complicated part about Spring Boot is how the framework itself can be reconfigured through dependency injection. When you provide a certain "bean", this can affect the auto-configuration, so that other beans, which you might expect, are no longer automatically created. To debug this behavior, check out the relevant AutoConfiguration class (in your IDE, use the "go to class" shortcut and type something like FooAutoConfi..., e.g. JdbcAutoConfiguration).

In a good codebase, the configuration itself would be tested. For instance, if you did something a bit more complicated like connecting two JDBC databases at the same time, you would test that it read the configuration from the right sources and provides the expected beans.

by andor

3/30/2026 at 1:41:38 PM

Does this app take 5 minutes to start? That's so much dynamic Spring magic. Also, how do you keep track of control flow when anything at anytime could have been overridden by something else? It seems like tracing and debugging this thing would be like exploring someone else's codebase every time.

by robmccoll

3/30/2026 at 2:43:02 PM

The class loading magic means you need to be exceptionally careful about things that would otherwise be very innocuous. It’s the rule, not the exception - that your average spring boot app will be doing tons of expensive stuff at startup. Most of which is unnecessary and was not even intended.

The JVM doesn’t need this kind of thing either, and it gets a bad wrap from the J(2)EE days, and the “simple” replacement that Spring was supposed to be.

No doubt there’s some benefits to be had, but I don’t think the trade-offs are worth it, especially at larger scales.

by switchbak

3/30/2026 at 4:36:12 PM

Who cares about startup times if apps is started only when new version is deployed?

And 5 minutes is a bit long, maybe someone is doing some database operations during start?

by krzyk

3/30/2026 at 5:07:30 PM

I care because every second of that startup time is lost productivity and focus. For me and any developer on my team. Hot reload only works if no class or method has changed so that's not a solution. I've worked on codebases of similar size and complexity in many languages, and the developer experience of a compile and restart that takes less than five seconds is game changing.

by robmccoll

3/30/2026 at 5:51:12 PM

I can imagine a full build of the project(s) in TFA are on the order of several minutes to build/run the first, and maybe every time. I remember working on projects before SSDs were common that would take on the order of a half hour or more... the layers of abstraction were so that you literally had to thread through 15+ projects in two different solutions in order to add a single parameter for a query and it would take a couple weeks to develop and test.

That said, I did catch up on my RSS feeds during that job.

by tracker1

3/30/2026 at 5:03:40 PM

> It seems like tracing and debugging this thing would be like exploring someone else's codebase every time.

Oh man, just wait till you start sprinkling some AOP in there. My debugger is damn near useless sometimes as I try to follow bizarre paths between parts of my code.

by guzfip

3/30/2026 at 5:08:42 PM

Totally! But it doesn't have to be this way.

by robmccoll

3/30/2026 at 3:39:30 PM

The article talks about a specific solution they came up with. No way is this a representative example, they discard a typical pattern way at the top.

by smrtinsert

3/30/2026 at 1:41:21 PM

Hacker news likes to dunk on Spring Boot, but its usage in enterprises is very very high.

by sidcool

3/30/2026 at 3:07:40 PM

it doesn't mean that usage of something being very high is a clever idea.

lots of people take meth - so are you gonna take meth too.

```@EnableConfigurationProperties(CasConfigurationProperties.class) @EnableScheduling @ConditionalOnFeatureEnabled(feature = CasFeatureModule.FeatureCatalog.SimpleMFA) @AutoConfiguration @Import({ CasSimpleMultifactorAuthenticationComponentSerializationConfiguration.class, CasSimpleMultifactorAuthenticationConfiguration.class, CasSimpleMultifactorAuthenticationEventExecutionPlanConfiguration.class, CasSimpleMultifactorAuthenticationMultifactorProviderBypassConfiguration.class, CasSimpleMultifactorAuthenticationRestConfiguration.class, CasSimpleMultifactorAuthenticationTicketCatalogConfiguration.class, CasSimpleMultifactorAuthenticationWebflowConfiguration.class }) public class CasSimpleMultifactorAuthenticationAutoConfiguration { }```

this is what we mean by "JavaCulture" - java | JVM really wonderful things but the culture is what sets these things back

someone can't just go in and understand things - they have to understand a bunch of notations too.

then if you work at a place and try do things differently the same people will tell you to revise your PR cz it ain't software engineering (or it won't scale)

by dzonga

3/30/2026 at 3:31:04 PM

That's a ridiculously extreme example, IME. Having been working with Java for 25+ years, I've never seen anything like that in code written by a shop I worked at, FWIW. And as a corollary I'm about 100% certain that you could find some equivalent extreme case to use as an example to dunk on any language/platform.

this is what we mean by "JavaCulture" - java | JVM really wonderful things but the culture is what sets these things back

Maybe there are still some Java shops out there living like this. But to me, this is a 20 year old outdated notion. shrug

by mindcrime

3/30/2026 at 4:57:12 PM

You have worked at some outstanding java shops then! In my experience the article is precisely representative of Java culture even today

by theflyinghorse

3/30/2026 at 10:34:20 PM

I also have 20+ years of experience and haven't seen that type of code either.

I am however struggling to understand an over engineered Rust "micro" service at work. There's no language or framework that is free from this.

Maybe it's because I have not worked in typical enterprise companies?

Spring Boot can be a really quick way to get things done. My current job is not in enterprise, but we use Spring Boot for most of our services, and rarely have issues related to Spring itself. We have micro services handling many transactions per minute and starts up within 10 seconds. The CPU usage is low and decent memory usage, even on the small pod sizes that we use. There are ways to reduce the startup, but we do not have the need. The code is easy to reason about and new hires are productive within a short time.

by throwawey1234

3/30/2026 at 9:49:45 PM

Let's not go too far! I've seen some crap code, granted. But for the most part, the crap code I've seen is, I believe, stuff written by people who would have written crap no matter what language they were working in.

That said, I have in fact also had some outstanding and talented colleagues over the years as well. A point that's probably worth reflecting on, so thanks for the reminder.

by mindcrime

3/30/2026 at 5:01:44 PM

This is still relatively tame! I've seen stuff where there are layers of annotations some of which will spawn docker containers effectively bringing docker compose into java application as part of the set up. Some containers would need to come up, do a quick file change, then die and the the rest of configuration proceeded (this was for an automated test tool). Entirely stupid, could have been written with just couple classes of Java and a docker compose. But it is a culture. It is a culture that I think ultimately will destroy Java.

by theflyinghorse

3/30/2026 at 5:54:07 PM

FWIW, I think .Net Aspire is pretty interesting along a similar vein. I mostly just rely on shell scripts and docker-compose configuration(s) for dev though.

by tracker1

3/31/2026 at 9:25:34 AM

This is an extreme example, same can be conjured up for any framework, Node or Django or Rails.

by sidcool

3/30/2026 at 4:36:46 PM

dude, that is a configuration.

it is completely declarative and lives in the best place, near your code, not on some other inaccessible repository.

what have you preferred? a json file? a yaml one?

I had them, and I find the annotations are more readable than other solutions.

by _ZeD_

3/31/2026 at 12:15:44 AM

Exactly!

by dknj

3/30/2026 at 1:59:53 PM

Huh, Enterprise usage of Blackberry was very very high and then it was not. And at one point SOA, SOAP/WSDL/XML usage was very very high and now I am told in my very enterprise job I'd be fired if I dared bring those names up.

Usage being high doesn't say anything about quality or suitability of a product specially in enterprise settings.

by geodel

3/31/2026 at 9:26:06 AM

Honestly, it does. Enterprise software does need high reliability.

by sidcool

3/30/2026 at 2:59:47 PM

Even in startups, lots of places are on Spring Boot (albeit more often using Kotlin over Java).

by dukeyukey

3/30/2026 at 3:10:28 PM

My favorite stack, Kotlin with Spring Boot. A real delight to work with

by bberrry

3/30/2026 at 3:17:18 PM

Cuisine Magazine likes to dunk on McDonalds, but its the most popular choice of dining.

by the_gipsy

3/30/2026 at 1:55:14 PM

Yes but enterprise software is some of the worst software you will encounter.

by tonyedgecombe

3/30/2026 at 2:14:23 PM

Not Spring Boot's fault :)

by sidcool

3/30/2026 at 2:40:34 PM

Not a strong indicator that Enterprises have good taste though is it?

by __alexs

3/30/2026 at 2:25:02 PM

I'm not that deep into Java, but I was under the impression that things like Quarkus were starting to replace Spring in enterprise use...

by nilamo

3/30/2026 at 8:54:06 PM

We have a medium sized Quarkus app (~200kLOC) and Quarkus has been fantastic. Startup in JVM mode for our app is around 10 secs. Not blazing fast - but likely much faster than a typical Java enterprise app. I'm sure a few of those secs are spent doing things like pulling authz policies from github or due to having several thousand hibernate entities.

by nogridbag

3/31/2026 at 9:26:42 AM

Quarkus, Micronaut etc. are doing well. But Spring Boot is the giant of Java ecosystem.

by sidcool

3/30/2026 at 5:03:41 PM

It will take some time for Quarkus to become a significant enough presence in the market share. In my experience, for the majority of Java shops Spring Boot does just fine because it worked before and it will probably work in the future.

by theflyinghorse

3/30/2026 at 1:44:14 PM

it saves a lot of reinventing the wheel

by fiftyacorn

3/30/2026 at 1:52:51 PM

And at the same time, gives you a dozen of footguns. This is just a list for the gotchas in the "@Transactional" annotation - https://dev.to/closeup1202/8-spring-transactional-pitfalls-t...

Now read up on all the dozen of annotations. But yeah, we did not want to "re-invent the wheel".

by rockyj

3/30/2026 at 2:13:48 PM

Im comparing against node equivalent ORMs and find spring consistently better. Yeah ive got to read up on annotations - but when it comes to transactions its always worth revisiting them to check for changes

by fiftyacorn

3/30/2026 at 5:58:14 PM

Meh...

    await using cn = await pool.connect();
    const records = await cn.query<MyType>`
      SELECT ...
      FROM ...
      WHERE ...
    `;
    for await (const record of records) {
      ...
    }
Oh, spring is so much better...

by tracker1

3/30/2026 at 3:36:58 PM

And startups not in the SV echo chamber. They happily exist and make money without worrying about supply chain attacks and js engine of the week.

by smrtinsert

3/30/2026 at 6:10:32 PM

Keep in mind that a big part of the configuration complexity of CAS is because of how it's used and customized in the real world.

These kinds of infrastructure systems its very common to replace a bunch of the built in functionality with your own classes, and so there's alot of effort put into supporting that use case.

I helped build a large open source enterprise financial systems, and most of the deploying orgs used CAS for authN. Both CAS and the financial system was built with similar approach to extensibility.

by allador

3/31/2026 at 12:23:21 AM

[dead]

by dknj

3/30/2026 at 3:00:03 PM

Switched from Spring Boot to Ruby on Rails 3 years ago.

I expected to see some new Spring 'tricks' in this post, but it's pretty much regular things that people might do in larger codebases.

by moondowner

3/30/2026 at 4:16:08 PM

- Swap out Java for Kotlin. The Spring guys won't officially drop support for Java; but a lot of their recent releases are becoming very Kotlin centered. Seriously, it's much nicer to use from Kotlin. I've done both.

- Go for declarative Kotlin DSLs over annotation magic for most things. Much easier to debug. It's just function calls. And DSLs are nice in IDEs with autocomplete.

- Keep it simple. It's a huge framework. But you probably don't need most of it.

- Don't go Spring everything, a lot of stuff in Spring is a bit experimental (Spring AI/MCP stuff) or a bit bare bones (Spring Data, it's a limited and extra level of indirection you mostly shouldn't need) or flat out misguided/over-engineered (Spring Batch, good alternatives are available for that).

- Decide on synchronous or asynchronous IO. The former is a lot more scalable now that Java has green threads. The latter is relatively painless from Kotlin but an absolute PITA from Java. They are very different internally and both have their pros/cons. If you need async, Kotlin co-routines is the easier path to do that. Either way, it's one of the bigger decisions to take.

- Don't copy their way of deeply nested inheritance hierarchies. Very much in fashion 20 years ago; a bit of an anti pattern now. Internal code complexity is the part I like least about Spring. And it has some really byzantine stuff in there with 5-6 levels of inheritance or worse.

by jillesvangurp

3/30/2026 at 7:20:57 PM

There's a lot of good ideas in Spring and there have been some outstanding engineers working on that framework over the past ~25 years. But it has accumulated so much baggage and relies on and perpetuates so many patterns that simply don't make sense anymore... I would love to see what the team would do with a fresh start. I wonder if they have or are considering doing a complete rewrite or starting something totally new for the next generation that will take us through the next 25 years of Java.

by dlandis

3/30/2026 at 4:18:54 PM

> What makes the CAS codebase impressive is the discipline of applying all of them consistently, across 400 modules, for years.

I think this is the main point. You can write good code in any language following this concept.

by exabrial

3/31/2026 at 12:28:08 AM

That's really the whole thesis. None of the patterns in the article are clever or novel - @ConditionalOnMissingBean has been in the Spring Boot docs since day one. What's hard is getting a team to apply it on every single bean, in every single module, for years, without anyone cutting corners. Discipline scales. Cleverness doesn't.

by dknj

3/31/2026 at 7:18:33 PM

100%

by exabrial

3/30/2026 at 3:56:32 PM

Bodyless classes only for carrying annotations... too much magic for my taste.

by fpauser

3/31/2026 at 12:34:26 AM

That's fair - it does look odd in isolation. But the alternative is mixing "should this load?" conditional logic with "what should load?" bean definitions in the same class. When you're debugging why a feature didn't activate across 272 entry points, having one place to look at - just the annotations on an empty wrapper - beats scanning through 200 lines of bean definitions hunting for the one @Conditional that blocked everything. It's not magic, it's separation of concerns applied to auto-configuration. Looks weird, works well.

by dknj

3/30/2026 at 5:16:40 PM

I wonder how many of these rules can be enforced with static analysis and ArchUnit.

by EricRiese

3/31/2026 at 12:37:06 AM

Good question - quite a few actually. @ConditionalOnMissingBean on every public @Bean method, proxyBeanMethods = false on every @Configuration class, the thin wrapper pattern (auto-config classes must have empty bodies) - those are all structurally checkable. CAS doesn't use ArchUnit specifically, but the consistency you see in the codebase didn't happen by accident. The patterns that can't be easily enforced statically are the harder ones - like making sure every module contributes to shared capabilities through the configurer pattern instead of direct coupling. That's where code review discipline fills the gap.

by dknj

3/30/2026 at 4:23:39 PM

[flagged]

by mergeshield

3/30/2026 at 1:44:39 PM

I recently inherited java code base.

Just rewrote it in Go. Now we are using a server which consumes 30% of ram what the existing one used to and the latency and throughput have all improved.

Don't use these stupid java backend like sprinboot.

by faangguyindia

3/30/2026 at 2:07:12 PM

I wouldn’t reduce it to don't use Java/Spring Boot. Rewrites often (not always) look great because they remove years of accumulated complexity, not because the original stack was inherently bad.

Just rewrite it in X doesn't "just work" for complex systems. It ignores risk, and the fact that design usually matters more than language.

by ludovicianul

3/30/2026 at 3:07:21 PM

i made 1 to 1 copy, not sliming anything.

by faangguyindia

3/30/2026 at 3:09:58 PM

usually what you say is correct. but in case of entreprise java, just look at the article. you have no way of knowing or controlling which essential class your application will be running because some intern merged a similarly named class two hundred levels down in the codebase and now that is handling all your db queries. and it's not a bug but a highly praised feature.

it's useless abstractions for the sake of useless abstractions.

java was designed so that american architecs could write a few interfaces and cheap workforce overseas could implement the actual code.

and the EE stuff evolved in a way that features could be shipped just by adding a new component that would inject itself in the right places. java "engineers" have no idea how http or cookies work, but they know where to load the spring-auth bean in a 2mb maven config.

so, any rewrite from java is an exception to the rewrites are only good because you cleaned up old features rule.

by iririririr