Engineering Practitioner Brief / 18 May 2026

Java and Spring Legacy Cost

Java has unusually long-lived production deployments and Spring is the framework most of them run on. That combination makes Spring upgrades the most common single-framework cost line in enterprise tech-debt conversations. This page collects the per-step cost across the JDK ladder (8 to 21), the Spring ladder (3 to 6), and the Java EE to Jakarta EE rename that wraps both. Numbers assume US fully-loaded engineer rates of around $85 per hour.

The JDK Ladder

Java versions matter for Spring because each Spring major has a JDK floor. Spring 5 requires Java 8. Spring 6 requires Java 17. The JDK ladder is therefore a prerequisite for the Spring ladder, and the cost of moving each step is roughly stable per application.

FromToMajor Breaking ChangesHours / 100K LOC
JDK 8JDK 11Module system, removed APIs (com.sun.*), CMS GC removal40 to 80
JDK 11JDK 17Sealed classes, pattern matching, fewer breaking changes20 to 40
JDK 17JDK 21Virtual threads, sequenced collections, mostly additive12 to 30
JDK 8JDK 21 (full ladder)Cumulative of above70 to 150

The JDK 8 to 11 step is the most expensive single hop because of the Java Platform Module System and the removal of internal com.sun.* APIs that many libraries depended on. The JEP 320 removal of CORBA and Java EE modules from the JDK (JDK 11) also forces affected applications to add explicit dependencies they had previously been getting for free. The official Oracle JDK Migration Guide enumerates the changes per release.


The Spring Ladder

Spring releases maintain backward compatibility well enough that single-major-version upgrades are usually straightforward. Multi-major jumps compound the deprecation work and often pull in transitive library upgrades that have their own breaking changes.

FromToNotable ChangesHours / 100K LOC
Spring 3Spring 4Java config preferred, JDK 6+ baseline40 to 100
Spring 4Spring 5JDK 8+, reactive stack added, JUnit 5 support60 to 140
Spring 5Spring 6JDK 17+, javax to jakarta rename, removed deprecated APIs120 to 280
Spring Boot 1Spring Boot 2Reactive support, actuator endpoint changes50 to 120
Spring Boot 2Spring Boot 3Spring 6 baseline, javax to jakarta, observability80 to 200

The Spring 5 to 6 step is the most expensive single hop in the modern era because of the javax-to-jakarta rename. Spring Boot 3 inherits the same constraint. Most teams treat the JDK upgrade, the Spring upgrade, and the Jakarta rename as a single multi-month project rather than three sequential ones, because the test and deploy overhead is dominated by the cutover and is paid once.


The Java EE to Jakarta EE Rename

When Oracle transferred Java EE stewardship to the Eclipse Foundation in 2017, the Eclipse Foundation was prohibited from continuing to use the javax package namespace for new versions. The result was the Jakarta EE 9 release in 2020, which renamed every javax.* package to jakarta.*. Spring 6 and Spring Boot 3 require Jakarta-namespace APIs.

The mechanical part is well-handled by the OpenRewrite migration recipes: import statements, fully-qualified names in strings, and most third-party library references get rewritten automatically. The harder part is libraries that have not yet published Jakarta-namespace versions. As of 2026, the major libraries (Hibernate, Tomcat, Jetty, Jersey, Bean Validation implementations) all have Jakarta-namespace releases. Smaller libraries and internal forks often do not, and have to be either upgraded, patched locally, or replaced.

Reference timing: a 200K-line Spring application with a typical library footprint takes 100 to 250 engineer-hours for the namespace rename alone, of which 60 to 80 percent is handled by OpenRewrite. The remaining hours are manual repairs for libraries without Jakarta releases.


The Legacy CI Tax (Hudson and Ancient Jenkins)

Hudson was renamed Jenkins in 2011. Some enterprise installations are still running Hudson, or running Jenkins versions from before 2018. The Jenkins security advisory feed publishes dozens of CVEs per year, some of which affect old core versions that are no longer eligible for patches. The decision to leave legacy Jenkins running is the decision to accept that risk.

The cost of upgrading a 10-year-old Jenkins is dominated by plugin recreation. Modern Jenkins plugins often have different configuration interfaces than their old counterparts. Pipeline scripts written for freestyle jobs do not run on declarative pipelines without rewriting. Some plugins are abandoned and have no modern equivalent, forcing a substitute plugin choice or a custom build step.

Typical sizing: 80 to 300 engineer-hours per Jenkins instance, plus 4 to 12 hours per build pipeline rewrite. For an enterprise running 50 build pipelines on a legacy Jenkins, the full migration is a quarter-long project. Migration to a managed CI like GitHub Actions, GitLab CI, or CircleCI is usually a similar magnitude of work and reduces the long-term maintenance overhead. See the sister site cicdcost.com for the comparative-cost arithmetic.


The Dependency Layer Beneath Spring

Spring rarely runs alone. The libraries that show up most often in Spring tech-debt audits are also the ones that block upgrades:


Recommended Sequence for a Spring 3 / JDK 8 Starting Point

A pragmatic ordering when starting from a Spring 3, JDK 8, javax-namespace baseline:

  1. JDK 8 to JDK 11. The biggest single-hop JDK cost; pay it first while still on a stable Spring 4 or 5.
  2. Spring 3 to Spring 5 in two steps (3 to 4, then 4 to 5). Build pipelines and tests should still run cleanly on JDK 11 throughout.
  3. JDK 11 to JDK 17. Smaller hop, sets up Spring 6 eligibility.
  4. Apply the OpenRewrite javax-to-jakarta recipe on the Spring 5 codebase. Verify in a long-running branch.
  5. Spring 5 to Spring 6, with the Jakarta namespace already in place. The Spring 6 upgrade becomes mostly mechanical.
  6. JDK 17 to JDK 21. Additive for most applications; virtual threads become available for new code.

Total elapsed time for a 200K-line Spring application: typically 12 to 18 months of effort, with shipping continuing throughout via the ladder pattern. See framework migration cost for the per-LOC summary across multiple stacks.

Related Reading


Frequently Asked Questions

How much does it cost to upgrade Spring 3 to Spring 6?

For a 100K-line Spring application, plan $120K to $280K across 6 to 14 months. The cost is dominated by the JDK upgrade (Java 8 to 17 minimum, 21 preferred), the Java EE to Jakarta EE namespace migration, and the deprecation cleanup across three major Spring releases (3 to 4 to 5 to 6).

What is the hardest part of the Spring migration?

The javax.* to jakarta.* package rename forced by Spring 6 and Spring Boot 3. Every import statement that touches Servlet API, JPA, JAX-RS, or Bean Validation has to be rewritten. OpenRewrite recipes handle the mechanical part well. The harder part is third-party libraries that have not published Jakarta-namespace versions yet.

Do I need to upgrade JDK at the same time?

Yes. Spring 6 requires Java 17 as a minimum. If you are on JDK 8 or 11, the JDK upgrade is a prerequisite. The JDK upgrade alone (JDK 8 to JDK 21) is typically 20 to 50 engineer-hours per application for the basic compile-and-run work, plus more if the app uses internal JDK APIs that were removed in later versions.

Is the OpenRewrite recipe pack worth using?

Yes. The OpenRewrite community recipes for Spring Boot upgrades, the javax-to-jakarta rename, and the Jakarta EE 9 to 10 migration cover the mechanical work reliably. A team that used to spend 2 to 3 days on the mechanical part of a Spring Boot major upgrade now spends 2 to 3 hours. The architectural work that comes after still has to be done by humans.

What about Spring Boot 2 to Spring Boot 3?

Spring Boot 3 brought the same javax-to-jakarta rename and a Spring 6 baseline. The official Spring Boot 3 migration guide enumerates the breaking changes; the OpenRewrite recipe handles the bulk of the mechanical work. Plan 80 to 200 engineer-hours per service for a typical Spring Boot 2 to 3 upgrade with full test verification.

What does legacy Jenkins or Hudson cost?

A legacy Jenkins or Hudson installation that has not been upgraded in years carries security risk (the Jenkins security advisory feed is long) and maintenance risk (plugins drop support for old core versions). A typical migration from a 10-year-old Jenkins to a modern Jenkins or to GitHub Actions costs 80 to 300 engineer-hours, dominated by recreating plugin pipelines in the new system.

Updated 2026-04-27