Migrating 350,000 Lines from Java/JSP to TypeScript with AI Agents
Skip to content
AI & Machine Learning
How I Migrated a 350,000-Line Java/JSP Application to TypeScript in Five Days
Published by
krishnagokula
on
July 31, 2026
Featured image generated locally with ComfyUI through the WSL gateway for the Java/JSP-to-TypeScript migration article.<br>" data-image-caption="AI agents supplied the migration throughput; verification converted it into measurable progress.<br>" data-large-file="https://i0.wp.com/gokulakrishna.co/wp-content/uploads/2026/07/ai-agent-java-to-typescript-migration.jpg?fit=1024%2C566&ssl=1" />
I recently migrated a 350,000-line Java/JSP application to TypeScript using AI agents.
Our original estimate for a conventional migration was three engineers and close to a year. Instead, one engineer orchestrating pools of up to 20 sub-agents at each stage got the application running in a development environment in five days.
The headline sounds like a story about faster code generation. It is not.
The decisive factor was verification. Once the agents had a reliable way to compare the old and new systems, parallelism became useful rather than chaotic.
350,000
lines of Java/JSP
5 days
to a running development environment
20
sub-agents in each stage
Why parallel agents were only half the solution
Jarred Sumner’s account of the Bun rewrite gave me useful ideas for running agents in parallel. Bun had an important advantage: a language-independent TypeScript test suite. The implementation could change while the expected behaviour remained measurable.
Our application had no equivalent safety net.
Only about half of the existing tests worked. Many had weak or missing assertions, and others depended directly on infrastructure. A large agent pool could generate code quickly, but without an independent oracle it could also produce 20 plausible versions of the wrong system.
We needed a way to answer a simple question at every stage: does the new application behave like the one already running?
The migration sequence
Database<br>APIs<br>UI<br>Business logic<br>Improvements
That order was deliberate. Each stage created a more stable foundation for the next, and it limited the number of variables that could change at once.
1. Reconstructing the database contract
The legacy application did not have a reliable database schema we could treat as authoritative.
We reconstructed the application-facing Oracle schema from the SQL queries embedded throughout the codebase. The agents identified tables, columns, joins, constraints and data assumptions from the queries, then we validated the reconstructed contract against the running system.
This was more than a database exercise. The schema defined the vocabulary shared by every API, page and business rule that followed. Starting anywhere else would have forced the agents to build on guesses.
2. Rebuilding the APIs
Once the data contract was stable, agents could migrate API components in parallel. Each work item was narrow: rebuild a component, exercise it against both systems, compare the result and resolve the discrepancy.
This gave the UI migration a dependable backend target instead of asking agents to infer behaviour simultaneously at every layer.
3. Migrating the UI
The UI required more than checking HTTP status codes. We needed to know whether the same data appeared, whether the same elements were present and whether the same interactions produced the same outcomes.
This is where the parity harness became the centre of the migration.
Building a parity harness where tests were missing
The parity harness ran the legacy and TypeScript applications side by side and compared them at three levels:
API responses and resulting database state<br>Page elements and screenshots<br>User interactions in both applications
Inline editorial image generated locally with ComfyUI through the WSL gateway for the parity-harness section.<br>" data-image-caption="The parity harness compared observable behaviour across the legacy and TypeScript systems.<br>" data-large-file="https://i0.wp.com/gokulakrishna.co/wp-content/uploads/2026/07/ai-agent-parity-harness.jpg?fit=1024%2C566&ssl=1" src="https://i0.wp.com/gokulakrishna.co/wp-content/uploads/2026/07/ai-agent-parity-harness.jpg?resize=1216%2C672&ssl=1" alt="A symmetrical amber and teal visualization of a parity harness comparing legacy and TypeScript application stacks." class="wp-image-156" srcset="https://i0.wp.com/gokulakrishna.co/wp-content/uploads/2026/07/ai-agent-parity-harness.jpg?w=1216&ssl=1 1216w, https://i0.wp.com/gokulakrishna.co/wp-content/uploads/2026/07/ai-agent-parity-harness.jpg?resize=300%2C166&ssl=1 300w, https://i0.wp.com/gokulakrishna.co/wp-content/uploads/2026/07/ai-agent-parity-harness.jpg?resize=1024%2C566&ssl=1 1024w, https://i0.wp.com/gokulakrishna.co/wp-content/uploads/2026/07/ai-agent-parity-harness.jpg?resize=768%2C424&ssl=1 768w" sizes="(max-width: 1000px) 100vw, 1000px" />The parity harness...