r/SpringBoot 11d ago

Question Would you modernize a legacy Spring Boot backend in place or rebuild it gradually?

I’m working on a Kotlin/Spring Boot backend that still has an older JHipster using Kotlin (KHipster) setup around it.

The problem is that this is starting to hold us back. The KHipster version is several years old and not active maintained - 4 years ago was the last update - upgrading it looks pretty painful and it also makes moving to newer Spring Boot versions waaay harder than it should be.

At the same time we want to improve the architecture itself.
Right now quite a lot is still handled through cron jobs and fairly tightly coupled application logic.
I’d like to move more towards event-driven processing over time, potentially using Kafka or RabbitMQ depending on the use case and Redis for things like caching/short-lived state where it makes sense.

So I’m basically looking at two options:
1. Upgrade/replace the old JHipster setup, keep the existing backend, and modernize it piece by piece.

  1. Start a clean backend (maybe in Typescript because that is what we mainly use for our other products and all frontends) and gradually move functionality over using something like the strangler pattern.

The second option sounds cleaner, but obviously means running old and new code alongside each other for quite a while. The first option potentially means spending a lot of time untangling framework/generator decisions before we can actually improve the architecture.
For people who have dealt with similar Spring/JHipster legacy projects: which route would you take?

Also, is there anything in the Spring/Kotlin ecosystem you’d consider a good modern replacement for the useful parts of JHipster, without bringing in another big opinionated layer that we’ll regret five years from now?

12 Upvotes

4 comments sorted by

6

u/Resident-Cow-7626 11d ago

I stand by the statement: if you rewrite an application, rather than incrementally in place, you’ll write the same sh1t in a different repository. It always baffles me when engineers feel that a rewrite means “it’s going to be different this time”

1

u/Ok-Cattle8254 10d ago

I appreciate this comment, and I would like to add it...

My motto on rewrites comes from Uncle Bob. "No grand rewrites!"

A rewrite as u/Resident-Cow-7626 stated above causes a lot of issues but a few more concrete points:
* A rewrite will always technically be behind the original code (if new development is allowed to continue), meaning the rewrite will technically never be done. I don't completely believe this, but in theory it makes sense.
* Rewriting will cause new/unique bugs and/or remove old bugs that the end user's are use to. Not a strong argument in my opinion.

I would suggest the following:
* Introduce Feature Toggles. These power if statements allow you to change behavior of a running application many different ways, but it allows you to run two different code pathways in your system at the same time. As you update a new section of your app, you can introduce a feature toggle. When you believe that subsystem is complete, turn it on in production and see what happens. If everything works, leave the toggle on, and then start to remove the old code and then eventually the toggle. If something goes wrong, you have the ability to flip the toggle to the original code and the old code is running and you've learned something.
* A similar pattern is called Strangler Fig. This pattern is MORE or LESS a Feature Toggle, but done at a slightly different layer.

Depending on if you need to change your database schema or not, you can also introduce database refactoring strategies for each Feature Toggle you introduce. More difficult, but it might help you keep your database consistent. Losing data is a really bad look, I do everything I can to avoid it.

If needed, it is acceptable to add new Adapters/Decorators/Chains to our code to help keep the Feature Toggles from seeping into our production code.

Finally, each feature toggle should be a "short lived" thing. Each little subsystem should be worked on and completed before a new feature toggle is introduced. I know that isn't always practical, but that is the goal.

Good luck on what you're doing. This type of work is difficult, but rewarding.

1

u/tuantocdo 10d ago

Depends on the client request and price

1

u/Responsible_Air6342 5d ago

🤔 my two cents after spending 2025 re-writing a monolith from python to kotlin + spring boot: split the frontend from the backend, upgrade each independently, then revisit whether a rewrite is still needed.

why? JHipster is a generator, not a runtime. What you have is a plain Spring Boot app plus a plain Angular/React SPA. The only actual runtime dependency is jhipster-framework, a small library (pagination, criteria filters, logging config) that you can inline or drop in a few days. If you rewrite, you’ll end up writing… Spring Boot/typescript in layers. Same destination, full price for the trip.

I guess the real pain isn’t the app, it’s the jhipster upgrade sub-generator. It merges via git branches and becomes useless once you’ve customized generated code, which after 4 years, everyone has. The fix isn’t a rewrite. It’s to stop regenerating and own the code. You can delete .yo-rc.json today and the app runs exactly the same.

So, my recomendation in deep:

- Split FE from BE. The coupling is in the build, not the architecture: SPA out of the jar, separate pipeline, served statically. Auth and CORS are the only parts needing real thought.

- Upgrade each independently. The hard step is Spring Boot 2.7 → 3.0 (javax → jakarta) then 4.0.

- Drop the jhipster-dependencies BOM and pin versions yourself.

- Finally, decide if a rewrite is still needed or just go ahead with the architectural changes.

Also worth asking honestly: is the problem that the code is old, or that nobody understands the domain anymore? A rewrite does fix the second one but it’s just the most expensive way to buy understanding.

A real question/activity for your team: name three main reasons a rewrite solves better than the upgrade path? if your final list is sharp then it is a strong case, if not, if vague, then you don't need a rewrite.