The conventional wisdom is destructive: “COBOL is old. Rewrite in Java. Move to the cloud.”
This advice comes from people who haven’t traced the actual cost. Rewriting business logic is expensive. It introduces bugs. It takes years. It requires hiring developers who understand both systems.
An alternative exists: wrap the COBOL logic. Run it on a modern platform. Keep the business logic intact.
The True Cost of Rewriting
A financial institution has a COBOL system that calculates interest rates, applies penalties, and determines eligibility for products. The system has 50,000 lines of COBOL. Ten developers maintain it. It processes 10,000 transactions per day correctly.
The institution wants to modernize. The plan: rewrite in Java, move to cloud, decommission the mainframe.
The estimate:
- 12 months of development
- 5 developers
- 1 QA team
- Infrastructure for parallel operation
Cost: $2-4 million in wages and infrastructure. Timeline: 12-18 months.
The rewrite starts. Developers begin translating COBOL to Java. Business analysts document the logic. The Java version is written. It works in testing.
The first release to production finds a bug. The COBOL version calculated a specific compound interest rate that the Java version calculates differently because of floating-point precision. Results diverge. The reconciliation job catches it. The Java version is held back.
The team fixes the rounding logic. They retest. They release again.
Three weeks later, another bug appears. The COBOL version handles negative account balances differently than the Java version—it truncates instead of rounding. The logic is subtle and wasn’t documented. Revenue reports diverge.
Each bug requires investigation, fixing, retesting, and rereleasing. Each cycle takes 2-4 weeks. After three months, the Java version is still not trusted. The business continues running the COBOL version.
The project timeline extends. Developers are now 9 months into a 12-month project and still fixing bugs. The pressure mounts. The organization decides to “just stop using COBOL” and force-migrate to Java, bugs and all.
Revenue divergences appear in subsequent months. Customers are charged wrong interest rates. Refunds are issued. Audits investigate. The project that was supposed to be complete is now in crisis mode.
The actual cost: $4-6 million (overruns), 24-30 months (timeline extension), plus legal costs for the incorrect charges.
The Logic is Worse Than the Code
The code is not the main problem. COBOL is verbose, but it’s mostly straightforward. Loops, conditionals, variable assignments—basic programming.
The logic is the problem. Why does the system calculate interest this way? What rules apply to different product types? When does the penalty apply? What are the boundary conditions?
The original developers understood this. The current developers partially understand it. New developers understand none of it. The knowledge exists in the code and in the (sometimes inconsistent) documentation.
Rewriting requires extracting this logic precisely. One missing edge case, one misunderstood rule, and the new system produces wrong results.
Some organizations document the logic before rewriting. They create specifications from the COBOL code. But the specifications are often post-hoc rationalizations. The code does things for reasons that aren’t documented. A specification says “apply 2% penalty when balance is negative.” The code has a condition that applies the penalty when balance < 0 AND product != “STUDENT_LOAN” AND account_age > 30_days. The condition is right there in the code. The specification is incomplete.
Other organizations rewrite incrementally. They translate a piece at a time, test it against the COBOL version, and if it matches, commit the Java version. This is slower but safer. A piece-by-piece rewrite of 50,000 lines takes 18+ months because testing each piece is expensive.
The Wrapping Alternative
Instead of rewriting, wrap the COBOL. The COBOL logic runs unchanged. A Java wrapper calls it.
This requires:
- Exposing the COBOL entry points (functions/procedures)
- Marshaling data between Java and COBOL
- Running the COBOL on a platform that supports Java interop
The platform exists: IBM Enterprise COBOL, Micro Focus COBOL, COBOL compilers that run on Linux/Windows. The interop exists: JNI, native libraries, containerized COBOL.
The solution:
public class InterestCalculator {
private final CobolRuntime cobolRuntime;
public InterestCalculator() {
this.cobolRuntime = CobolRuntimeFactory.getRuntime();
}
public double calculateInterest(Account account, Period period) {
// Call COBOL function directly
return cobolRuntime.call(
"CALCULATE-INTEREST",
account.getBalance(),
account.getRate(),
period.getDays()
);
}
}
The Java code handles HTTP requests, REST APIs, database updates. The COBOL code handles business logic. The boundary is clear. The COBOL is not rewritten.
Timeline: 4-6 months. Cost: $500k-1M in development and infrastructure.
The risk is lower because the COBOL logic is unchanged. The main risk is the integration—does the marshaling work? Are the data types compatible? These are technical questions with clear answers, not business logic questions filled with assumptions.
The Phased Modernization
The wrapped approach enables gradual modernization. Instead of rewriting everything, rewrite modules that need updating.
A new requirement arrives: “Support subscription pricing.” The old system doesn’t support it. The organization can either:
- Implement subscription pricing in COBOL and maintain that code
- Implement subscription pricing in Java alongside the old interest logic
The second option is faster. The Java module handles subscriptions. The COBOL module handles interests. They coexist. The COBOL code doesn’t grow. The Java code is new and maintainable.
public class PricingEngine {
private final CobolRuntime cobolRuntime;
public Price calculatePrice(Account account, Product product) {
if (product.getType() == ProductType.SUBSCRIPTION) {
// New logic in Java
return calculateSubscriptionPrice(account, product);
} else {
// Old logic in COBOL
double interest = cobolRuntime.call(
"CALCULATE-INTEREST",
account.getBalance(),
product,
account.getPeriod()
);
return new Price(interest);
}
}
private Price calculateSubscriptionPrice(Account account, Product product) {
// Java implementation of subscription pricing
}
}
Over time, modules migrate from COBOL to Java. The COBOL code shrinks. The Java code grows. At some point, the COBOL is small enough to decommission. The migration is complete without a “big bang” rewrite.
Timeline: 2-3 years of gradual migration. Risk: low per phase because each phase is independent.
The Performance Question
A concern: wrapping COBOL adds overhead. Each call from Java to COBOL requires marshaling, context switching, memory conversion.
The overhead is real but small compared to the business logic runtime. Interest calculations take milliseconds. The marshaling overhead is microseconds. The total impact is single-digit percent.
For batch jobs, the overhead is negligible. A batch that processes 100,000 transactions spends 95% of the time on I/O (database queries, file reads). Five percent on logic. Wrapping adds 1% overhead to the 5% logic portion, resulting in 0.5% total overhead. Imperceptible.
If the overhead becomes a problem, the wrapped approach still wins. The bottleneck is identified (which function is slow?), the function is optimized (rewrite that one function in Java), or architectural changes are made (batch differently). The alternative path—rewriting everything at once—prevents this kind of targeted optimization.
The Maintenance Reality
COBOL code that’s maintained in production for 30 years has proven reliability. The edge cases are understood. The bugs are fixed. The code works.
java code written by a team learning the business domain for the first time has unknown reliability. Edge cases are discovered in production. Bugs appear in production. The code needs months of hardening before it’s trustworthy.
The wrapped approach preserves the reliability of the COBOL while adding modern infrastructure around it. The Java code is small—it’s plumbing, not business logic. Plumbing is easier to test and less fragile than business logic.
When Rewriting Makes Sense
Rewriting is sometimes justified:
- The COBOL code is unmaintainable (undocumented, over-complicated, no developers understand it)
- The business logic is fundamentally broken and needs reimplementation
- The platform the COBOL runs on is literally shutting down (mainframe decommissioning, OS EOL)
- The organization has specific performance requirements that COBOL can’t meet
These are rare. Most organizations rewrite out of preference (“let’s use modern languages”), not necessity.
If the COBOL works and requires maintenance only occasionally, wrapping is more rational. If the COBOL is failing frequently and business logic is unclear, rewriting might be necessary.
The Organizational Impedance
The biggest obstacle to wrapping is organizational. IT departments prefer rewriting because it justifies new hiring, new technologies, and a fresh start. Operations prefers wrapping because it doesn’t require learning new systems. Business prefers wrapping because it’s cheaper and faster.
The political battle is real. IT departments pitch rewriting as “modernization” and “moving away from legacy.” Business hears “risky, expensive, slow.”
Some organizations navigate this by doing both: a smaller rewrite for new components and wrapping for existing components. The organization gets the “modern stack” they want (Java, cloud) and the cost-efficiency of not rewriting 50,000 lines of COBOL that work.
The Hidden Cost of Correctness
A rewritten system has a hidden cost: correctness validation. Proving the new system produces the same results as the old system is expensive.
The validation requires:
- Running both systems in parallel (double infrastructure)
- Comparing results on every transaction
- Investigating discrepancies (why do they differ?)
- Fixes and revalidation (repeated many times)
- Gradual traffic migration (10% to new system, 25%, 50%, 100%)
This takes months. During this time, the organization is running two systems. The cost is high.
The wrapped approach avoids this. The COBOL is unchanged. It produces the same results as before. Validation is not needed because there’s nothing new to validate. The new Java code is integrated around the unchanged COBOL. Testing is localized to the integration points.
The Technical Debt Perspective
Technical debt is often framed as “old code is bad, new code is good.” This is backwards.
Technical debt is the cost of maintaining a system. Old code that works and requires little maintenance is a low-debt asset. Old code that requires frequent fixes and has many bugs is high-debt liability.
COBOL code that’s worked for 30 years and needs modification once a year is low-debt. Rewriting it introduces debt: new code, uncertain reliability, knowledge loss.
The wrapped approach acknowledges technical debt accurately. It preserves the low-debt COBOL. It adds controlled Java code around it. The total debt decreases over time as the Java code matures and edge cases are resolved.
The Pragmatic Path
Organizations that want to modernize their platforms have a choice:
Path 1: Rewrite. Take 18-24 months, spend $2-4M, rewrite business logic that works, introduce new bugs, validate extensively, migrate carefully, decommission the old system. Big risk, big cost, big timeline, big uncertainty.
Path 2: Wrap. Take 4-6 months, spend $500k-1M, preserve working business logic, integrate with modern infrastructure, gradually modernize, maintain both systems until comfortable. Small risk, small cost, fast timeline, high confidence.
Path 3: Hybrid. Wrap for now, rewrite over time as modules need updating or as the organization gains confidence in rewritten modules. Combine the benefits: fast time-to-modern-platform, risk controlled, cost managed, knowledge preserved.
The fastest path to a modern runtime is not to rewrite the business logic. It’s to wrap it.