A small Java project can move to Kotlin in days; a mature monolith may demand quarters of engineering time.

The cost of a Java-to-Kotlin migration is set early, when the codebase is still small enough to change in one pass. I moved a project that way with little effort. The system I work on now contains hundreds of thousands of Java lines in a monolith, making a wholesale conversion a bet no one is likely to approve.
Why migration costs grow
A small project gives engineers room to change direction quickly. There are fewer classes to convert, fewer dependencies to check, and fewer teams whose work might be disrupted. When the application is still compact, developers can often make the language change alongside ordinary feature work and address problems as they appear.
That calculation shifts as software accumulates. A large monolith can contain years of assumptions about data, error handling, build steps, testing, and interactions between components. Translating syntax is only one part of a migration; teams also have to confirm that behavior remains the same and that Java and Kotlin code can coexist safely while the conversion proceeds.
The burden isn't limited to the files being edited. A change in one area can affect shared libraries, deployment pipelines, developer tools, and the habits of engineers who maintain the system. The bigger the codebase, the harder it becomes to treat conversion as a bounded cleanup task.
What a Java-to-Kotlin conversion involves
Java and Kotlin both run on the JVM, which makes gradual adoption technically possible in many environments. Kotlin can call Java code, and Java can interact with Kotlin code, so a team doesn't necessarily have to convert an application in one sweep. That compatibility lowers the barrier to starting, but it doesn't make a large migration free.
Mixed-language systems bring their own coordination work. Developers need to understand how types and null handling cross language boundaries, how generated or framework-dependent code behaves, and which conventions apply in each part of the application. Build and test tooling must also support the combination. Each issue may be manageable on its own; across a large monolith, the checks add up.
Then there's the question of what the conversion is meant to achieve. Kotlin may offer language features a team finds useful, but rewriting code doesn't automatically improve architecture, reliability, or delivery speed. If the main problem is tangled dependencies or unclear ownership, changing languages can leave that problem intact while adding migration work on top.
The roadmap is part of the cost
The option remains technically available, but the work has grown from days to quarters of engineering time. That's a different kind of decision. A team considering a migration at that scale has to compare it with product development, maintenance, and other reliability work that also competes for engineering capacity.
Estimates can also be misleading when they count only conversion effort. Engineers must review the results, update tests, resolve compatibility issues, and support the system throughout the transition. If the migration spans multiple releases, the organization may have to maintain two sets of language practices and keep the application working throughout the change.
Here's the thing: the expense often becomes visible only after the language choice has been around long enough to shape the system. By then, the migration isn't just a matter of preference. It's a portfolio decision about where limited engineering time will have the most effect.
Why early choices carry weight
Across more than a decade building high-load distributed systems on the JVM for fintech, security, and media infrastructure, I've seen the same pattern: migration costs accumulate before the work reaches a roadmap. The practical takeaway is to weigh language choices while the codebase can still move in a single pass.
This is more significant than it looks. Early choices can influence not only syntax, but also the examples new engineers learn from, the libraries teams standardize on, and the boundaries they draw between components. Those decisions aren't irreversible, yet reversing them becomes harder as more code and more people depend on them.
If you're working in this space, the useful question isn't simply whether Kotlin is better than Java for a given team. Ask how the choice fits the project's expected life, how much code is likely to accumulate, and whether the organization can make a later transition without displacing more valuable work. (And this is the part most people overlook.) The cost of keeping options open is real, too: teams need consistent conventions and should avoid turning a small codebase into a patchwork without a clear reason.
Implications for teams
For a new or small project, the decision can be tested while the code is still easy to change. Teams can assess language fit through actual maintenance and development work, rather than treating a later migration as an abstract possibility. A limited trial can reveal practical friction in tooling and collaboration before those choices spread across a large application.
For an established monolith, the case for conversion needs to be concrete. A gradual path may reduce disruption, but it still asks engineers to spend time on migration alongside ongoing development. And yet, waiting has a cost of its own: the larger the system becomes, the less plausible a single, clean conversion may feel. Sometimes the sensible result is to keep the existing language and focus on the problems that matter most.
Not a free option. A deferred one.
Discussion
Sign in to join the discussion.