StripeMahib HosainProblem & solution
Modern Java at Stripe: Language upgrades as a service
Summary
Large JVM codebases often stall Java upgrades because build-graph constraints require coordinated changes across many owners, while manual scripts and stale inventories repeatedly rediscover blockers. Stripe built AutoJDK to continuously analyze the live build graph, compute eligibility using reverse-dependency, runtime, framework, and dependency-ordering constraints, and generate bounded, idempotent pull requests rather than opaque rewrites. It also tracks adoption and blocker categories, uses AI assistance for selected remediation tasks, and can operate continuously or on specified packages and services. Centralized JDK and runtime policy, CI checks, multi-JDK support, static analysis, and packaging applications with platform-specific JDKs support gradual transitions. After three months, the upgrader had merged more than 160 PRs, made JDK 17 the most common target, eliminated Java 8 services, and reduced the JDK 8 and 11 footprint by roughly 25K targets.
Context
Large Java upgrades at scale were recurring, quarter-long projects that depended on bespoke scripts, stale inventory data, and manual reasoning across complex build graphs. These migrations slowed after easy targets were handled, left blockers poorly documented, and required the same compatibility facts to be rediscovered for each new JDK move.
Approach / What changed
AutoJDK continuously analyzes the live build graph and compatibility constraints to identify eligible Java and Scala targets, generates bounded reviewable PRs in partitions, and tracks adoption and blockers. It supports continuous or targeted reruns, uses AI assistance and Minions for selected remediation work, and operates within centralized JDK policy, CI checks, multi-JDK support, static analysis, and platform-specific JDK packaging.
Takeaways
AutoJDK determines upgrade eligibility using reverse dependencies, runtime compatibility caps, dependency ordering, framework guards, source-and-test coordination, and Bazel macro constraints.
Bounded, partitioned, idempotent PR generation keeps large upgrade waves reviewable, mergeable, and safe to rerun instead of producing giant opaque rewrites.
Within three months, the system merged 160+ PRs, eliminated Java 8 services, and reduced the JDK 8 and 11 footprint by roughly 25K targets.
Source and freshness
- Source
- stripe.dev
- Published
- Added to Yomu
- Last updated
Summaries are generated from the original by a language model. Check the original before relying on it.
Keep reading
Related reading
The Good Stuff
Paid picks we use ourselves. Links carry a referral code — a subscription through one earns us a commission at no extra cost to you.
The best engineering reads, once a week
One useful email. Unsubscribe anytime.