Where COBOL in production still does the real work
See where COBOL in production runs today, why it survived, what finally forces replacement, and how to preserve behavior during a rewrite.

COBOL remains in production where an organization has spent decades encoding money, entitlement, and exception handling into one dependable operational path. The language is visible in the source library, but the system also includes JCL, schedulers, files, databases, transaction monitors, operator procedures, reconciliation reports, and agreements with every system around it. Replacing only the programs replaces the least difficult part.
The familiar line that "banks still use COBOL" is accurate and nearly useless. It hides which workloads still depend on it and why their owners keep paying to run them. COBOL is concentrated in batch settlement, insurance policy administration, core banking ledgers, and government benefit calculation. These systems stayed on because they kept producing correct business outcomes under ugly conditions. They move when the cost of change becomes lower than the combined risk of staff loss, platform constraints, slow product change, and an interface boundary nobody can safely extend.
The production map follows money and entitlement
COBOL is still used where a large, durable record must survive many transactions and where someone must explain the result later. Four workload classes account for much of the serious production estate.
Batch settlement takes a day's accepted activity, applies fees and adjustments, balances control totals, posts results, and emits files for downstream parties. The online front end may use a newer language while the final financial state still comes from COBOL jobs scheduled after a cutoff.
Policy administration holds the contractual history of insurance products. It calculates premiums, applies endorsements, renews policies, produces bills and documents, and records what coverage existed on a particular date. A web portal can sit in front of this system without replacing it.
Core banking ledgers post debits and credits, maintain balances, accrue interest, enforce posting rules, and close accounting periods. Mobile apps and payment APIs are channels. The ledger decides what the bank believes happened.
Government benefit calculation applies statutes and program rules to claims, earnings histories, household facts, effective dates, overpayments, and appeals. The Social Security Administration's budget material, for example, describes claim processing across siloed legacy COBOL systems. That is a concrete operational dependency, not nostalgia for an old language.
These categories overlap. A benefit platform has ledgers. An insurer runs settlement batches. A bank administers products with policy-like effective dates. The useful distinction is the business invariant: settlement must balance, a policy must reproduce coverage as of a date, a ledger must preserve accounting truth, and a benefit system must explain an entitlement decision.
Batch settlement is a controlled chain, not one program
A settlement estate is a timed dependency graph whose output has financial consequences. A typical night starts only after channels close their input windows. Jobs validate file counts, sort records, enrich transactions, calculate charges, post summaries, compare totals, create outbound files, and route exceptions to operations. A rerun may start at one safe checkpoint rather than at the beginning.
IBM's z/OS documentation calls batch processing a fundamental z/OS function and explains how JES receives jobs, schedules them, and controls their output. That description matters because it corrects a common modernization error: the COBOL executable does not own the whole workflow. JCL names inputs and outputs, cataloged procedures supply shared steps, the scheduler supplies calendars and dependencies, and operators interpret return codes and spool output.
A small job fragment shows how much behavior lives outside the application source:
//SETTLE JOB CLASS=A,MSGCLASS=X
//POST EXEC PGM=POSTDAY,PARM='RESTART=CHK7'
//INTRANS DD DSN=BANK.CLEARING.ACCEPTED,DISP=SHR
//OUTPOST DD DSN=BANK.LEDGER.POSTED(+1),
// DISP=(NEW,CATLG,DELETE)
//EXCEPT DD DSN=BANK.SETTLE.EXCEPT(+1),
// DISP=(NEW,CATLG,DELETE)
//SYSOUT DD SYSOUT=*
The replacement must answer questions the fragment exposes. What creates generation (+1)? Does a failed step delete partial output? Which return codes allow the next job to run? What does CHK7 mean after a partial posting? Who decides whether an exception file is complete? Converting POSTDAY to another language without recreating those controls can produce valid code and an invalid settlement process.
Settlement systems remain because they are optimized around cutoff discipline, restartability, and bulk I/O. They finally move when new channels require more frequent posting, counterparties demand different file or API boundaries, batch windows collide with global operating hours, or too few people understand how to recover a failed chain.
Policy administration preserves time as business data
A policy administration system must answer "what was true then?" as well as "what is true now?" Effective dates, transaction dates, retroactive endorsements, cancellations, reinstatements, renewals, jurisdictional rules, and product versions all affect the answer. That temporal model is why a simple database migration rarely replaces the system.
Consider an endorsement entered today but effective before the last bill. The system may need to recalculate premium across part of a term, preserve previously issued documents, generate a new receivable, and leave an audit trail that explains the difference. A naive service that stores only the latest policy state destroys evidence. A faithful replacement treats events, effective periods, derived values, and issued artifacts as separate concerns.
COBOL fits this work because fixed business records, decimal arithmetic, sequential processing, and explicit branches match the domain. The surrounding estate often adds copybooks shared by many programs, tables maintained outside code, document templates, rating modules, and nightly billing jobs. Some rules appear twice because online quoting and renewal billing evolved separately. The duplicate logic may disagree only on a rare product version, which is exactly when a clean rewrite can change a valid customer outcome.
Owners did not switch these systems off merely because browsers and app servers changed. They added portals, workflow tools, and APIs around them. That was rational while products remained stable and the core produced defensible results. The decision changes when launching or changing a product requires edits across old programs, when every release depends on a shrinking review group, or when an unsupported document or integration component blocks the whole path.
A replacement should prove temporal behavior with dated fixtures. Test a new policy, a midterm endorsement, a backdated correction, a cancellation followed by reinstatement, and a renewal across a product-version boundary. Compare money, status, coverage periods, documents, ledger entries, and explanations. Matching the current row in a policy table is not enough.
Core ledgers survive because accounting errors compound
A core ledger is still running COBOL because changing the posting engine can alter the institution's books. The work includes much more than adding and subtracting balances. Posting order, value dates, holds, reversals, interest accrual, fee assessment, currency precision, suspense handling, and end-of-period controls interact.
The field often blurs a ledger with a balance service. A balance service answers a read request quickly. A ledger records ordered, durable entries and supports reconstruction. If a migration copies current balances but loses posting history or reversal relationships, the numbers can match on cutover morning and become impossible to explain after the first dispute.
Online transaction handling commonly runs through CICS. IBM's Enterprise COBOL documentation explains that programs using CICS services compile embedded CICS statements through the CICS command interface. That detail signals another boundary a rewrite must discover: transaction scope may depend on CICS resources, Db2 work, files, queues, and error handling rather than on COBOL statements alone.
Ledger replacement fails in recognizable ways. A team maps account rows to new tables, reimplements happy-path postings, and proves a set of unit tests. During parallel run, an old reversal arrives after the related transaction crossed an accounting date boundary. The new system applies today's rule and the old system applies the rule version attached to the original entry. Both executions look reasonable. Only one matches the institution's established books.
The answer is not to keep every historical implementation defect. The team must classify behavior. Accounting invariants and contractual outcomes require parity. Accidental display formatting may not. A suspicious rule needs an explicit business decision, recorded before anyone "fixes" it. Otherwise engineers make policy choices inside code review, where nobody can see the financial consequence.
Benefit calculation combines law with operational history
Government benefit systems keep COBOL because the executable rules sit on top of long claimant histories and administrative procedure. A calculation may depend on earnings periods, household composition, disability status, prior determinations, program interactions, effective dates, rounding rules, caps, offsets, and later corrections. Appeals can require the agency to reproduce a decision using the facts and rules that applied at the time.
The statute is not the executable specification. Regulations, policy manuals, table updates, batch calendars, data-cleaning rules, and exception procedures close the gap between legal language and a payment. Two records that appear equivalent to a new service can follow different paths because an old indicator captures how the agency resolved an earlier discrepancy.
Modernization programs get into trouble when they treat odd fields as obsolete before tracing their use. A one-character code may select a calculation branch, suppress a notice, send a case to manual review, or preserve a prior adjudication. Removing it can change a person's payment without causing a software error. The program runs, the API returns success, and the defect appears only when a claimant or caseworker challenges the result.
A benefit replacement therefore needs decision-level evidence. For each recorded case, capture normalized inputs, rule version, intermediate calculations, final amount, effective period, notices, reason codes, and manual-review routing. Redact or tokenize personal data before it leaves its permitted boundary. In a regulated environment, test infrastructure and models may need to run inside the same perimeter as the source data.
The pressure to replace rises when legislative changes take too long to implement, old interfaces prevent agencies from joining records safely, staff can no longer explain certain paths, or platform procurement narrows. Public scrutiny makes a rushed rewrite especially dangerous. Faster change matters, but reproducible decisions matter more.
These systems stayed because replacement risk was asymmetric
Keeping a working COBOL estate was often the financially sensible choice. The downside of delay accumulated slowly as maintenance cost, slower delivery, and staffing exposure. The downside of a faulty replacement arrived at once as incorrect balances, failed settlements, wrong coverage, or miscalculated payments.
Several conditions reinforced that asymmetry. Mainframe transaction and batch facilities already handled workload scheduling, access control, recovery, and high-volume I/O. Hardware and compiler upgrades extended the platform without forcing an application rewrite. Stable file layouts let newer channels integrate at the edge. Most important, the business had production evidence that the old path worked, including decades of exceptions that no requirements document captured.
The popular claim that COBOL persisted because management was afraid of change is too shallow. Managers funded many changes around these cores. They replaced terminals with web interfaces, introduced message brokers, exposed services, and moved reporting elsewhere. They avoided replacing the stateful center because the business case did not offset the risk.
Another popular recommendation is to translate every COBOL paragraph into equivalent code in a newer language. It is attractive because it produces a measurable conversion rate and keeps behavior close to the source. It is also wrong as an end state. A paragraph-for-function translation preserves global state, file-shaped boundaries, batch assumptions, and decades of structural compromise. The organization then owns a mainframe design in an unfamiliar syntax, often with worse operational tooling.
A sound decision separates three questions. Is the current platform reliable enough for the next planning horizon? Can the organization change business rules at the required speed? Can it still recover and explain failures without depending on one or two people? A "yes" to the first does not cancel a "no" to either of the others.
Longevity also creates false confidence about documentation. Run books often describe the normal schedule and the last recovery procedure someone bothered to write down. They do not necessarily record why a control total excludes one source, why a file must arrive before another, or why an operator accepts one nonzero return code but stops on the next. Those choices survive as habit. A migration discovers them when a parallel run diverges, which is late and expensive.
Treat operational knowledge as production logic. Observe a complete cycle, including cutoff, restart, reconciliation, late input, and manual repair. Ask operators to explain the evidence they trust, then connect that evidence to the job and data that produced it. If a person keeps a private spreadsheet or command list to close the day, include it in scope even when architecture diagrams omit it. The replacement needs a supported control or an explicit decision to retire the practice.
Do not confuse a quiet system with a simple one. Mature cores often look quiet because operators absorb irregularity before it reaches incident management. Count manual interventions, reruns, overrides, reconciliations, and calls to former team members. Those signals show whether stability comes from the software or from people compensating for it.
The forcing event is usually outside the COBOL compiler
COBOL itself rarely sets the deadline. The decision becomes unavoidable when an external constraint removes the option to wait. A vendor ends support for a database, screen layer, scheduler, or integration product. A merger requires two incompatible ledgers to become one. A new product needs intraday behavior from an overnight core. A regulatory change demands traceability the current workflow cannot produce cheaply. A critical maintainer leaves and recovery knowledge leaves with them.
Platform cost can contribute, but a license comparison alone is a weak migration case. Distributed replacements have their own compute, observability, storage, network, security, and staffing costs. If the proposal needs implausibly cheap infrastructure to work, it will fail when production volume and retention arrive.
Staffing risk also needs precision. "COBOL developers are retiring" does not tell a CTO what to approve. Measure ownership at the business-function level. Identify which people can explain month-end restart, which can change a premium rule, which know why a posting code bypasses a queue, and which can reconcile a benefit run. The danger is concentrated knowledge, not the average age of a language community.
Architecture pressure becomes decisive when every new capability must route through a few rigid files or transaction boundaries. Teams add adapters, duplicate reference data, and wait for batch confirmation. Eventually the cost appears as product delay and operational ambiguity rather than a mainframe invoice. At that point replacement has an owner outside infrastructure: the executive responsible for launching products, combining operations, or meeting a statutory date.
Use a forcing-event memo before approving work. Name the constraint, the date or condition that makes it binding, the affected business outcomes, the acceptable coexistence period, and the evidence required for cutover. If the memo says only "technical debt," the scope will wander because nobody has defined the decision the project must enable.
The migration risk lives in behavior between components
A reliable rewrite starts by discovering observable behavior across the whole estate. Source analysis matters, but code alone cannot reveal scheduler overrides, operator actions, live data shapes, undocumented consumers, or rules embedded in tables. The inventory must connect programs to jobs, data sets, database objects, queues, screens, reports, and downstream acknowledgements.
Begin with production paths rather than repository folders. For one business outcome, trace the initiating event to the final posting or notice. Record every component, input, output, side effect, checkpoint, and recovery action. Then repeat for exceptions: duplicate input, missing reference data, partial database failure, late arrival, restart after output creation, and manual correction.
A behavior record can use a plain shape like this:
{
"case_id": "settlement-late-file-restart",
"inputs": ["accepted-transactions", "fee-table-v17"],
"pre_state": "checkpoint-6-complete",
"action": "restart-from-checkpoint-7",
"outputs": ["posted-generation", "exception-generation"],
"invariants": ["debits-equal-credits", "no-duplicate-posting"],
"evidence": ["job-log", "control-report", "ledger-query"]
}
The record is deliberately independent of an implementation. It says what must remain true and where proof comes from. Build records from actual production variants, then add constructed edge cases for boundaries that production traffic may not exercise during the observation window.
Run the old and new paths against the same accepted input and compare normalized outcomes. Normalization should remove values that may legitimately differ, such as generated identifiers or timestamps, while preserving money, dates, status, ordering where material, reason codes, and side effects. Store mismatches as reviewable artifacts. A green count without the actual diff encourages teams to waive unexplained differences.
Recorded traffic is strong evidence, but it is not a complete specification. It proves only the cases observed. Pair it with source-derived branches, copybook values, table domains, operator interviews, and reconciliation procedures. This distinction matters: replay tests measure compatibility with observed use, while rule tests cover valid behavior that did not happen during capture.
Security and privacy constraints shape the method. Production records can contain account, policy, health, or identity data. Keep capture, tokenization, model execution, and comparison inside the permitted environment when data cannot leave. Preserve referential relationships in tokenized fixtures or many cross-record rules become untestable.
Data representation deserves its own test surface. Copybooks can describe packed decimals, signed fields, overlays, repeating groups, and values whose meaning depends on another field. Files may use EBCDIC, fixed record lengths, or site-specific conventions for missing values. A parser that silently trims spaces or normalizes an invalid date can merge states the old system kept distinct. Generate boundary fixtures from every declared field shape, then compare parsed values and rejected records before testing business rules.
Shared copybooks do not guarantee shared meaning. One program may treat a code as an account status while another treats the same bytes as a routing decision. Trace reads and writes, not names alone. Where layouts changed over time, identify which producers can still send each version and how consumers distinguish them. This work prevents a new canonical model from erasing information that a late file or historical replay still needs.
Data conversion and application replacement also create different risks. Converting a historical store proves that records can reach the target shape. It does not prove that tomorrow processing will create the right new records. Test opening balances and history conversion separately from transaction behavior, then join them in a dress rehearsal that crosses a real accounting or billing boundary. Reconcile record counts, control totals, balances, unmatched references, and every rejected item. A total that matches can still hide two equal and opposite errors, so sample at the entry and customer level as well.
Performance tests must reproduce the shape of work, not merely its average volume. A settlement run has arrival spikes and a hard completion time. An online ledger has latency requirements plus contention around popular accounts. A benefit recalculation may read deep history and emit several side effects. Preserve ordering and lock conflicts in the test data, measure restart time after failure, and include downstream consumption. A fast producer that overwhelms the next system has not improved the business path.
Treat return codes and operator messages as interfaces until proved otherwise. Schedulers branch on them, support teams search for them, and procedures may use them to decide whether an output is complete. Map each old condition to a typed failure, retry rule, alert, and recovery action in the target. Make idempotency explicit: rerunning after a timeout must not post money twice, issue a document twice, or suppress an exception because a partial record already exists.
The review group should include the people who reconcile outcomes, not only the people who maintain source. Finance operations can explain which totals certify settlement. Policy staff know which dated documents must remain reproducible. Caseworkers know which reason codes lead to manual review. Their evidence turns a technical diff into a cutover decision. Without it, a team can close thousands of code-level mismatches and still miss the one difference that changes a liability.
Finally, set a policy for unknown behavior. When the old path produces an unexplained result, do not automatically copy it and do not quietly correct it. Quarantine the case, preserve inputs and evidence, assign a business owner, and record the chosen target behavior. This queue will contain defects, obsolete rules, and legitimate exceptions. Its closure rate is a more honest readiness measure than the percentage of source files converted.
Replace the boundary and prove the cutover
The target should modernize ownership and interfaces while preserving required outcomes. Define bounded services around business capabilities, choose a durable data model, and make batch and online responsibilities explicit. Do not let the old program structure dictate every module. Do let its behavior constrain every externally material result until the business approves a change.
A practical sequence has five parts:
- Freeze an inventory of production entry points, scheduled jobs, stores, and consumers for the chosen business slice.
- Build the parity harness before the replacement so every implementation decision receives the same evidence.
- Implement the new architecture behind stable adapters, including restart, reconciliation, and operator controls.
- Run historical fixtures and recorded production traffic through both paths, classifying every difference.
- Cut over with explicit rollback criteria, then keep reconciliation active until the agreed risk window closes.
Choose slices that end in a verifiable business outcome. "Convert 200 programs" is not a slice. "Process one settlement source through posting and reconciliation" is. The latter exposes dependencies and gives executives evidence they can evaluate.
CodeHero applies this approach by reading the COBOL, JCL, and the rest of the tree together, rewriting the architecture into Go, Rust, TypeScript, and Postgres, then checking behavior with a parity harness against recorded production traffic. Its projects are delivered in under 30 days, including air-gapped execution inside the customer perimeter when the environment requires it.
Speed does not remove the owner's cutover responsibilities. The organization still decides which behaviors are contractual, which anomalies should be corrected, what evidence satisfies risk and audit teams, and who can authorize rollback. Those decisions cannot be inferred safely from source code.
A COBOL system should not move because its syntax looks old. It should move when the current boundary blocks the business and when the replacement can show, case by case, that money, entitlement, history, recovery, and explanation still work. Approve the rewrite when both conditions are true.
FAQ
What industries still use COBOL in production?
Banking, insurance, government administration, payments, and other record-heavy operations still run important COBOL workloads. The useful question is which business outcomes depend on it, not whether a company has any COBOL files.
Is COBOL still used for banking transactions?
Yes. COBOL commonly participates in ledger posting, account processing, settlement, interest, fees, and transaction handling around mainframe systems. A modern mobile or API channel does not prove that the ledger behind it is modern.
Why have companies not replaced their COBOL systems?
The existing systems kept producing dependable outcomes, while a faulty replacement could damage balances, coverage, settlement, or payments immediately. Organizations often modernized channels around the core because that gave them benefits without taking the largest operational risk.
Is a COBOL system insecure because it is old?
Age alone does not determine security. Risk depends on supported components, access controls, patching, identity boundaries, data handling, operational practice, and whether anyone can still change and recover the system safely.
What usually triggers a COBOL modernization project?
A binding event usually triggers it: lost expertise, an unsupported dependency, a merger, a new product requirement, a statutory change, or an integration boundary that cannot meet demand. A vague desire to reduce technical debt rarely controls scope well enough.
Can COBOL be converted automatically to a modern language?
Syntax can be converted, but a useful replacement must also recover behavior from JCL, data, schedulers, transaction monitors, tables, and operator procedures. Pure translation tends to preserve the old architecture and gives the organization awkward new code with old constraints.
How do you test a rewritten COBOL application?
Run old and new paths against the same inputs and compare normalized business outcomes, side effects, logs, and reconciliation evidence. Add source-derived edge cases because recorded production traffic cannot cover every valid branch.
Should a COBOL migration preserve every old behavior?
No. Preserve accounting, contractual, statutory, and operationally required behavior. Classify apparent defects and obsolete presentation details explicitly so business owners, not engineers acting alone, decide whether they should change.
Can sensitive mainframe code be modernized in an air-gapped environment?
Yes, if the tooling and models can run inside the customer perimeter and the workflow keeps source, data, and evidence there. The team must still design tokenization, access, retention, and review controls for its own regulatory obligations.
How should a CTO scope the first COBOL migration slice?
Choose one end-to-end business outcome with observable inputs, outputs, reconciliation, and rollback criteria. A program count is a poor scope because it ignores dependencies and does not prove that any useful operation works.