
How to Modernize a COBOL Payment Processing Platform Without Breaking the Business
COBOL modernization is not simply about rewriting old code. For payment processors, the real challenge is understanding business rules, batch flows, data lineage, job dependencies, and operational risk before changing the platform that runs the business.
A company may want APIs, cloud analytics, lower operating costs, and less dependence on scarce mainframe expertise, but none of that can be achieved safely without first understanding how the existing platform actually works. In a payment environment, the COBOL programs are only one part of the system.
If your organization is dealing with a business-critical COBOL or mainframe platform that is difficult to change, document, integrate, or modernize safely, Sharp Logica can help with an architecture-led Legacy Systems Assessment, modernization roadmap, and practical execution support. You can book a 30-min free call, view the services, or email us at info@sharplogica.com with specific questions.
Introduction
Last week I visited a friend in New York’s Financial District, where he works at a company we’ll call NorthBridge Payments. Being in the heart of global finance, surrounded by sleek offices and fast-moving markets, it’s easy to assume everything is powered by the latest technology. But as we talked, it became clear that beneath the surface, much of the industry still depends on decades-old legacy systems. These systems quietly handle enormous volumes of critical transactions every day, forming the backbone of operations that people rely on without ever seeing.
At NorthBridge Payments, the push to modernize is a constant topic, but the reality is far more complex than simply upgrading software or replacing old code. The challenge sits at the intersection of technology, business risk, and operational continuity. Deeply embedded systems are difficult to replace because they support critical payment flows, and even small changes can have significant downstream effects across settlement, reconciliation, reporting, exception handling, and partner integrations. Strict regulatory and compliance requirements also limit how quickly the platform can evolve, while the shrinking pool of engineers experienced in COBOL and mainframe environments makes long-term maintenance increasingly difficult. For companies like NorthBridge Payments, modernization is therefore a careful balancing act between innovation and stability, where gradual evolution is often the only viable path.
What makes this challenge especially striking is how widespread it remains across the industry. According to analyses and reports from organizations such as IBM and Gartner, a majority of the world’s financial transactions still run on mainframes, with commonly cited estimates suggesting that up to 95% of ATM transactions and around 80% of card payments rely on COBOL-based systems. In the insurance sector, the dependence is just as strong, with core processes such as policy management, claims handling, billing, and regulatory reporting still built on these long-standing platforms. These systems are not still in place because companies forgot to modernize them. They remain because they are reliable, scalable, and capable of processing enormous transaction volumes with a level of consistency, control, and auditability that is difficult to replace casually. At the same time, their importance creates a paradox: the systems most critical to global finance are often the systems that are hardest to modernize safely.
NorthBridge Payments has exactly this kind of problem. Its core payment processing platform still runs on a mainframe, and that platform continues to do what the business depends on every day. It processes large volumes of transactions, settles payments, posts fees, handles exceptions, creates reports, and keeps the financial engine of the company running. The issue is not that the system has suddenly stopped working. The issue is that the organization needs the platform to become more understandable, maintainable, integrated, and efficient without putting the business at risk.
But the company is becoming uncomfortable with it.
The system has not suddenly stopped working, and that is exactly what makes the situation more complicated. The concern is not immediate failure, but the growing gap between a platform that still runs the business and an organization that is finding it harder to understand, maintain, and evolve that platform safely. The people who know the system in depth may be retiring or moving on, documentation may no longer reflect how the platform really behaves, and even small changes may require long analysis because nobody is fully confident about downstream effects. At the same time, the business needs modern APIs, better access to transaction data, lower operating costs, shorter batch windows, and a realistic way to reduce long-term dependency on scarce COBOL and mainframe expertise.
This is where many companies make the first mistake. They define the problem as “we need to rewrite the COBOL”, because that sounds decisive and easy to understand at executive level. In reality, that is usually the wrong starting point. The real problem is not simply that part of the platform is written in COBOL. The real problem is that the system is not sufficiently understood, mapped, documented, tested, modularized, or exposed in a way that allows the business to evolve safely.
If I were brought in as the architect responsible for assessing and modernizing this environment, I would not begin with a rewrite proposal. I would begin by creating clarity around how the system actually works, which business capabilities it supports, where the critical dependencies are, which rules are embedded in code and jobs, and what risks the organization would face if it changed the wrong part too quickly. The first phase of modernization is therefore not transformation. It is discovery.
First, Understand That Mainframes and Modern Systems Think Differently
Before proposing any architecture, it is important to explain one basic thing to business stakeholders: mainframe systems are not primitive versions of modern systems. They were designed around a different operating model.
Modern systems are usually designed around interactive request-response flows. A customer opens a web or mobile application, clicks a button, an API is called, a service processes the request, a database is updated, and a response is returned immediately. The architecture is often distributed. It may use REST APIs, message queues, microservices, cloud databases, observability tools, containers, and event-driven workflows.
Mainframe systems often grew from a different world. They were designed to process large volumes of business-critical data with consistency, control, reliability, and throughput. In many environments, especially banking, insurance, and payments, the dominant model is not always “user sends request and receives immediate response.” It is often “large volumes of work arrive, are processed in controlled steps, reconciled, and reported.”
That distinction matters.
On IBM z/OS, business processing may involve COBOL programs, JCL jobs, datasets, DB2 tables, VSAM files, schedulers, reports, CICS transactions, and operational procedures. JES, the Job Entry Subsystem, manages submitted work and plays an important role in batch execution. The environment may also expose APIs and support online transaction processing, especially through CICS and newer tools such as z/OS Connect, but many older systems were not originally built around the API-first mindset that dominates modern software architecture.
In other words, the mainframe is not “just old code.” It is an operating environment, a processing model, a data model, a scheduling model, and a business control model.
That is why modernization cannot be approached as a simple code replacement exercise.
The Mainframe Approach: Batch, CICS, Jobs, and Reconciliation
In a payment processor such as NorthBridge Payments, some activities may be online and transactional. For example, a CICS transaction may allow an operator or another system to submit or inquire about a payment. But a large part of the real business may still happen in batch.
Payment files arrive from banks, merchants, networks, clearing partners, and internal systems. Jobs validate the files, enrich the records, apply rules, update balances, calculate fees, create settlement outputs, generate exception reports, and feed downstream systems. Some jobs run hourly. Some run at end of day. Some run overnight. Some run only after another job has completed successfully.
This is a very different mindset from a typical modern web application.
A modern application often thinks like this:
request -> process -> response
A mainframe-heavy payment platform may think more like this:
receive file -> validate -> process in bulk -> write outputs -> reconcile -> report exceptions
It may also support checkpoint and restart behavior. If a long-running batch job fails after processing two million records, the organization may not want to rerun everything from the beginning. The system may have a way to restart from a known checkpoint, isolate failed records, continue processing, and reconcile results later.
This is not a weakness. It is one of the reasons these systems survived for so long. The business world still has cutoffs, settlement windows, clearing cycles, audit requirements, exception handling, and reconciliation. Payments, banking, insurance, payroll, claims, and regulatory reporting still require controlled processing.
Centralized data also gives these systems real advantages. It can provide strong consistency, simpler reconciliation, clear ownership, and very high throughput processing. That is why many core systems still rely heavily on z/OS environments.
The challenge is that the same strengths can become obstacles when the company needs faster change, better integration, modern analytics, and broader access to business capabilities.
The Real Modernization Problem
When NorthBridge Payments says it wants to modernize, the concerns are typically practical business ones - I asked if they meant AI, knowing full well it was the wrong question, and they did their best not to laugh; it wasn’t something they were even considering.
The company may be struggling to find enough people who understand the system, while also dealing with change cycles that take too long and releases that feel risky because the downstream impact is not always clear. At the same time, modern customer channels require APIs, mainframe MIPS cost may be too high, batch windows may be under pressure, and cloud analytics may need governed access to operational data. Leadership may also want to reduce long-term dependency on COBOL and mainframe skills while preparing for an eventual migration, even if that migration will take years.
Those are all valid concerns, but they do not automatically point to one answer.
Some parts of the system may need to stay on the mainframe for a long time because they are stable, efficient, and deeply connected to core processing. Other parts may only need better documentation and testing, while some may need API enablement, replatforming, or targeted refactoring. Over time, selected capabilities may be replaced by new services or commercial platforms, while obsolete components may be retired completely.
The architect’s job is to separate these categories. Without that separation, modernization becomes a slogan instead of a plan.
The Actual Architecture Approach
I would approach the work in a sequence of practical steps, these steps are not just technical. They are designed to produce clarity for executives, architects, developers, operations teams, compliance teams, and business stakeholders.
The steps are:
- Understand the mainframe operating model.
- Inventory the system.
- Map jobs, data, dependencies, and business capabilities.
- Extract and validate business rules.
- Build documentation that the business can actually use.
- Create a risk register.
- Enable APIs where it makes sense.
- Modularize and identify service extraction candidates.
- Decide what to keep, wrap, refactor, extract, replace, replatform, or retire.
- Evaluate replatforming carefully.
- Evaluate automated refactoring or code conversion carefully.
- Treat full replacement as business transformation, not code conversion.
- Build a staged modernization roadmap.
Each of these steps has a different purpose.
Step 1: Understand the Mainframe Operating Model
The first step is to understand how the system runs today, not how people think it runs, not how it was documented years ago, and not how it should run, but how it actually runs.
For a payment processor, this means understanding the difference between online transaction flows and batch flows. Some work may happen through CICS transactions, where users or systems interact with the mainframe in near real time, while other work may happen through scheduled JCL jobs, where large sets of transactions are processed in bulk.
The architect needs to understand the daily rhythm of the system: when files arrive, when payments are validated, when exceptions are produced, when settlement files are created, when reconciliation is performed, which jobs are allowed to fail and restart, which jobs must complete before the business day begins, and which reports are used by finance, compliance, operations, or external partners.
This matters because a modern architecture cannot be designed in isolation from the old operating model. If the old system depends on end-of-day reconciliation, cutoff times, batch windows, and downstream reports, those concepts must either be preserved, redesigned, or consciously eliminated. They cannot simply be ignored.
Step 2: Inventory the System
The second step is inventory, and while that may sound basic, it is often where the most important discoveries happen.
The team needs to identify the real artifacts that make up the platform:
- COBOL programs
- JCL jobs
- datasets
- copybooks
- DB2 tables
- VSAM files
- schedulers
- CICS transactions
- upstream systems
- downstream systems
- reports
- control files
- error files
- reconciliation outputs
- business rules
The purpose of this inventory is not to create a long spreadsheet that nobody reads, but to answer real operational questions.
The team needs to understand which programs exist, which ones are still used, which ones are dead code, which jobs call which programs, which datasets are read and written, which copybooks define shared record structures, which DB2 tables are updated, which VSAM files are still critical, which outputs feed downstream systems, which jobs are part of settlement, which ones are only reporting, which ones are regulatory, and which ones are manual workarounds from fifteen years ago.
For a business person, the value is simple: before the company spends millions modernizing the system, it should know what the system actually contains.
Step 3: Map Jobs, Data, Dependencies, and Business Capabilities
Once the inventory exists, the next step is mapping, where the work starts to become architectural rather than purely technical.
Individual technical artifacts need to be connected into business and operational flows because a COBOL program by itself does not tell the full story, a JCL job by itself does not tell the full story, and a DB2 table by itself does not tell the full story. The value comes from understanding how these pieces work together.
The architect should build maps that answer practical questions such as what runs, when it runs, what data it reads, what data it writes, which jobs must complete first, which systems send input, which systems receive output, what business process the flow supports, what happens if a step fails, and what breaks if something changes.
For NorthBridge Payments, one map may show the transaction intake process, while another may show payment validation, settlement, exception handling, reconciliation, or regulatory reporting.
This is also where business capabilities begin to appear. Instead of seeing only technical artifacts, the organization starts to see the business functions hidden inside the system.
For example:
This kind of map is useful because it creates a shared language between business and technology. The business does not need to understand every COBOL paragraph or every JCL step. But it does need to understand which capabilities exist, how they depend on each other, and where the risk sits.
Step 4: Extract and Validate Business Rules
After mapping comes business-rule extraction, one of the most important parts of the modernization effort because the real value of the system is not the syntax of the COBOL code, but the business knowledge embedded inside it.
For a payment processor, rules may include things like:
- If a merchant is in a high-risk category, apply additional review before settlement.
- If a payment is not cleared after a defined number of days, move it to an exception status.
- If a transaction exceeds a limit, route it to manual review.
- If a settlement file is missing before the cutoff time, hold downstream reconciliation.
- If a customer account has a specific status, reject or suspend payment posting.
- If a partner sends an old file format, apply a legacy conversion rule before processing.
These rules may appear in different parts of the platform. Some may be written directly in COBOL, some may be implied by JCL sequencing, some may exist in DB2 tables, some may be buried in VSAM layouts, some may be enforced by operations rather than code, and some may be documented only in the heads of senior employees.
The architect’s responsibility is to extract candidate rules and then validate them with SMEs, because a rule found in code is not automatically a rule the business still wants. It may be obsolete, required by regulation, applicable only to one old partner, a temporary workaround that became permanent, or a business-critical rule that nobody remembers clearly.
AI can help here by summarizing COBOL programs, identifying conditional logic, explaining copybooks, detecting repeated patterns, and drafting documentation, but AI cannot decide whether a rule is still valid because that requires business validation.
The output should not be “AI-generated documentation”, but it should be a validated rule catalog that the business owns.
Step 5: Build Documentation That the Business Can Use
Documentation is often treated as a side effect of modernization, but that is a mistake. In legacy environments, documentation is one of the main modernization deliverables, because the company cannot safely improve a system it does not properly understand.
The documentation must also be useful. A giant technical document that nobody reads will not help the company, so the deliverables need to connect business, architecture, and operations in a way that executives, architects, developers, operations teams, and SMEs can all use.
For NorthBridge Payments, the useful deliverables would include:
- Business capability map
- Rule catalog
- Data lineage map
- Job dependency graph
- Integration map
- Risk register
- Modernization roadmap
The business capability map explains what the platform does, while the rule catalog explains which business decisions are embedded in the system. The data lineage map shows where data comes from, how it changes, and where it goes. The job dependency graph shows what runs, in what order, and what depends on what. The integration map shows upstream and downstream systems. The risk register identifies dangerous areas, and the modernization roadmap explains what should be modernized first, later, or not at all.
This is where the company moves from dependency on tribal knowledge to institutional knowledge, which is a major modernization outcome by itself.
Step 6: Create a Risk Register Before Designing the Future State
Many modernization efforts jump too quickly to the target architecture, drawing diagrams with APIs, services, cloud databases, message brokers, analytics platforms, and dashboards before the organization has properly understood the risk. Those future-state elements may eventually be useful, but they should not drive the modernization plan before the organization knows which parts of the existing platform are fragile, expensive, poorly understood, highly coupled, business-critical, or difficult to test.
The risk register should identify exactly those areas and make the risk visible before major architecture decisions are made. For example, a small copybook may be used by fifty programs, which means changing it may be far riskier than changing a large standalone program. A batch job that runs once per month may be more important than a job that runs every hour if it produces a regulatory report. A file that looks like a simple intermediate dataset may actually be the contract between two major business processes.
Risk is not always proportional to code size. It is proportional to dependency, business impact, change frequency, test coverage, operational knowledge, and failure consequences.
This is why architecture-led modernization is different from code-led modernization. The architect is not only asking “what is old?” The architect is asking “what is dangerous, what is valuable, what is connected, and what must be protected?”
Step 7: Enable APIs Where It Makes Sense
Once the system is mapped and understood, API enablement becomes much safer because the organization is no longer exposing mainframe capabilities blindly.
NorthBridge Payments may need to expose payment status, customer eligibility, merchant setup, transaction search, exception status, or settlement information to modern applications. A mobile app, partner portal, fraud platform, analytics dashboard, or customer service tool may need access to capabilities that still live on the mainframe.
One practical pattern is:
Modern app -> REST API -> z/OS Connect / CICS -> COBOL transaction
This approach does not require rewriting the core logic immediately. It creates a modern access layer around selected mainframe capabilities, allowing the company to serve new channels faster while preserving proven transaction logic.
APIs, however, should not be added blindly. If the underlying transaction was designed for internal use, has hidden timing assumptions, depends on batch reconciliation, or returns data that only makes sense in an operational context, exposing it through an API may create new problems.
A good architect will ask whether the capability is safe to expose, whether the data is current enough, whether the result depends on overnight batch processing, whether the operation is a command or a query, whether the transaction updates core data, whether it has proper error handling, whether it can handle the expected traffic, and whether the API creates a new dependency on a fragile part of the system.
The goal is not to create APIs everywhere. The goal is to create the right APIs around well-understood capabilities.
Step 8: Modularize and Identify Service Extraction Candidates
The next step is modularization, although this does not necessarily mean immediately creating microservices. It means identifying logical business capabilities that are hidden across programs, jobs, files, and tables, so the company can understand which parts of the platform can be improved, exposed, extracted, replaced, or left alone.
For a payment processor, these capabilities may include:
- Customer eligibility
- Merchant onboarding
- Transaction validation
- Payment posting
- Fee calculation
- Statement generation
- Settlement
- Exception handling
- Reconciliation
- Chargeback support
The first step is to create the capability map, and only then should the architect decide what should happen to each capability.
Some capabilities may stay on the mainframe, some may be wrapped with APIs, some may be refactored inside COBOL to improve maintainability, some may be extracted into separate services, some may be replaced by a SaaS or packaged solution, and some may be retired.
This is where the modernization plan becomes realistic. The company does not modernize “the mainframe.” It modernizes specific capabilities in a specific sequence.
Step 9: Decide What to Keep, Wrap, Refactor, Extract, Replace, Replatform, or Retire
A useful modernization roadmap needs a disposition decision for each major capability or component, because the options are not only “keep” or “rewrite.” A mature modernization plan usually contains several possible treatments, depending on the value, risk, cost, and complexity of each part of the system.
Some parts should be kept because they are stable, efficient, and not worth changing. Some should be wrapped because the business needs modern access, but the underlying logic is still valuable. Some should be refactored because the logic is good, but the structure is too hard to maintain. Some should be extracted because they represent a bounded capability that can safely move to a modern service. Some should be replaced by commercial software because the company gains no advantage from owning that logic. Some should be replatformed to reduce cost or improve operational flexibility. Some should be retired because they no longer serve a real business purpose.
This is a much better conversation than “COBOL versus cloud.” The real question is: which modernization treatment fits each business capability?
Step 10: Evaluate Replatforming Carefully
Replatforming means moving the workload off the mainframe with minimal functional change. For example, COBOL and JCL workloads may be moved to an emulated or compatible runtime environment on AWS, Azure, GCP, Linux, or another platform.
This can reduce cost, improve infrastructure flexibility, and make operations more familiar to modern teams, while also helping with DevOps practices, deployment automation, monitoring, and staffing.
However, replatforming is not the same as re-architecture. The application may still behave the same way, with the same batch flows, the same data structures, the same business rules, the same coupling, and the same maintenance complexity. That may be acceptable if the business goal is cost reduction or data center exit, but leadership should not confuse replatforming with true modernization of the business architecture.
Replatforming can be a good intermediate step because it can buy time, reduce operating pressure, and make the environment easier to manage. But it does not automatically make the system easier to understand or change.
Step 11: Evaluate Automated Refactoring and Code Conversion Carefully
Automated refactoring or code conversion is the “COBOL to Java,” “COBOL to C#,” or “COBOL to cloud-native” path.
This is attractive because it sounds direct: take the old code, convert it into a modern language, deploy it on a modern platform, and reduce dependency on COBOL.
However, there is a major risk: converted code can become ugly Java or C# that still thinks like COBOL. The syntax changes, but the architecture remains the same. The data structures remain unnatural, the control flow remains procedural and hard to follow, the batch assumptions remain, and the business rules remain tangled. The new code may be unfamiliar to COBOL developers and unpleasant for modern developers, which means this is not modernization. It is translation.
Automated conversion can be valuable, but only under the right conditions. The company needs strong test coverage, clear business-rule validation, parallel-run capability, data reconciliation, architectural review, and a plan for post-conversion refactoring. Otherwise, the organization may spend a large amount of money to move complexity from one language to another.
Step 12: Treat Full Replacement as Business Transformation
Full replacement is the hardest path because it means redesigning the business capabilities, creating a new data model, changing operational processes, building new user experiences, implementing new integrations, migrating historical data, validating rules, retraining teams, and running old and new systems in parallel until confidence is high.
That is not COBOL conversion, but a business transformation.
For NorthBridge Payments, full replacement would mean redefining payment intake, posting, settlement, exception handling, reconciliation, reporting, partner integration, fraud workflows, operational controls, and audit processes. This is expensive and risky, but sometimes necessary.
However, it should not be the first move unless the business has a very clear reason. A company earns the right to replace a core system by first understanding it.
Step 13: Build a Staged Modernization Roadmap
The final deliverable is the modernization roadmap, but this roadmap should not be a generic slide that says “move to cloud.” It should sequence real work based on risk, value, and readiness.
A practical roadmap for NorthBridge Payments might look like this:
Phase 1: Discovery and mapping.
Inventory COBOL programs, JCL jobs, DB2 tables, VSAM files, datasets, copybooks, schedulers, reports, and integrations. Build the current-state architecture map, job dependency graph, and data lineage map.
Phase 2: Business-rule extraction and validation.
Analyze COBOL and JCL, extract candidate rules, validate them with SMEs, and create a rule catalog connected to business capabilities.
Phase 3: Stabilization.
Improve documentation, logging, job monitoring, restart procedures, test coverage, and release controls. Reduce operational risk before making major changes.
Phase 4: API enablement.
Expose selected CICS or COBOL transactions through controlled APIs where business value is clear and technical risk is understood.
Phase 5: Data modernization.
Create safe pipelines for analytics and AI access, without disrupting operational systems or weakening data governance.
Phase 6: Capability-level modernization.
For each business capability, decide whether to keep, wrap, refactor, extract, replatform, replace, or retire.
Phase 7: Selective migration or replacement.
Move only the capabilities that justify the cost and risk. Run parallel processing where necessary. Validate outputs, reconcile results, and avoid big-bang migration unless there is no alternative.
This approach is slower than making a dramatic promise, but it is much safer because it gives the company control.
A Simple COBOL Example: Why Rewriting Is Not the Point
To make the problem more concrete, imagine that NorthBridge Payments has a COBOL batch program that reads a payment input file, validates each payment, assigns a status, writes approved payments to one output file, writes exception payments to another file, and produces basic counters for reconciliation.
This is still simplified compared to a real production program, but it is closer to the type of pattern one might see in a payment-processing batch flow.
IDENTIFICATION DIVISION.
PROGRAM-ID. PAYPOST.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT PAYMENT-IN
ASSIGN TO PAYIN
ORGANIZATION IS SEQUENTIAL.
SELECT PAYMENT-APPROVED
ASSIGN TO PAYAPP
ORGANIZATION IS SEQUENTIAL.
SELECT PAYMENT-EXCEPTION
ASSIGN TO PAYEXC
ORGANIZATION IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD PAYMENT-IN
RECORD CONTAINS 80 CHARACTERS.
01 PAYMENT-IN-REC.
05 IN-CUSTOMER-ID PIC X(10).
05 IN-MERCHANT-ID PIC X(10).
05 IN-PAYMENT-ID PIC X(12).
05 IN-PAYMENT-AMOUNT PIC 9(7)V99.
05 IN-CUSTOMER-STATUS PIC X(10).
05 IN-DAYS-PAST-DUE PIC 9(3).
05 IN-MERCHANT-RISK PIC X(01).
05 FILLER PIC X(25).
FD PAYMENT-APPROVED
RECORD CONTAINS 80 CHARACTERS.
01 PAYMENT-APPROVED-REC PIC X(80).
FD PAYMENT-EXCEPTION
RECORD CONTAINS 80 CHARACTERS.
01 PAYMENT-EXCEPTION-REC PIC X(80).
WORKING-STORAGE SECTION.
01 WS-END-OF-FILE PIC X VALUE "N".
88 END-OF-FILE VALUE "Y".
88 NOT-END-OF-FILE VALUE "N".
01 WS-PAYMENT-STATUS PIC X(12).
01 WS-EXCEPTION-REASON PIC X(20).
01 WS-TRANSACTION-LIMIT PIC 9(7)V99 VALUE 10000.00.
01 WS-COUNTERS.
05 WS-READ-COUNT PIC 9(9) VALUE 0.
05 WS-APPROVED-COUNT PIC 9(9) VALUE 0.
05 WS-EXCEPTION-COUNT PIC 9(9) VALUE 0.
05 WS-REJECTED-COUNT PIC 9(9) VALUE 0.
PROCEDURE DIVISION.
MAIN-PROCESS.
PERFORM INITIALIZE-PROCESS
PERFORM READ-PAYMENT
PERFORM UNTIL END-OF-FILE
ADD 1 TO WS-READ-COUNT
PERFORM VALIDATE-PAYMENT
PERFORM WRITE-PAYMENT-RESULT
PERFORM READ-PAYMENT
END-PERFORM
PERFORM FINALIZE-PROCESS
STOP RUN.
INITIALIZE-PROCESS.
OPEN INPUT PAYMENT-IN
OUTPUT PAYMENT-APPROVED
PAYMENT-EXCEPTION.
READ-PAYMENT.
READ PAYMENT-IN
AT END
SET END-OF-FILE TO TRUE
END-READ.
VALIDATE-PAYMENT.
MOVE SPACES TO WS-EXCEPTION-REASON
IF IN-CUSTOMER-STATUS = "SUSPENDED"
MOVE "REJECTED" TO WS-PAYMENT-STATUS
MOVE "SUSPENDED ACCOUNT" TO WS-EXCEPTION-REASON
ADD 1 TO WS-REJECTED-COUNT
ELSE IF IN-DAYS-PAST-DUE > 30
MOVE "EXCEPTION" TO WS-PAYMENT-STATUS
MOVE "PAST DUE" TO WS-EXCEPTION-REASON
ADD 1 TO WS-EXCEPTION-COUNT
ELSE IF IN-MERCHANT-RISK = "H"
MOVE "EXCEPTION" TO WS-PAYMENT-STATUS
MOVE "HIGH RISK MERCHANT" TO WS-EXCEPTION-REASON
ADD 1 TO WS-EXCEPTION-COUNT
ELSE IF IN-PAYMENT-AMOUNT > WS-TRANSACTION-LIMIT
MOVE "MANUALREV" TO WS-PAYMENT-STATUS
MOVE "LIMIT EXCEEDED" TO WS-EXCEPTION-REASON
ADD 1 TO WS-EXCEPTION-COUNT
ELSE
MOVE "APPROVED" TO WS-PAYMENT-STATUS
ADD 1 TO WS-APPROVED-COUNT
END-IF.
WRITE-PAYMENT-RESULT.
IF WS-PAYMENT-STATUS = "APPROVED"
STRING
IN-CUSTOMER-ID
IN-MERCHANT-ID
IN-PAYMENT-ID
IN-PAYMENT-AMOUNT
WS-PAYMENT-STATUS
DELIMITED BY SIZE
INTO PAYMENT-APPROVED-REC
END-STRING
WRITE PAYMENT-APPROVED-REC
ELSE
STRING
IN-CUSTOMER-ID
IN-MERCHANT-ID
IN-PAYMENT-ID
IN-PAYMENT-AMOUNT
WS-PAYMENT-STATUS
WS-EXCEPTION-REASON
DELIMITED BY SIZE
INTO PAYMENT-EXCEPTION-REC
END-STRING
WRITE PAYMENT-EXCEPTION-REC
END-IF.
FINALIZE-PROCESS.
DISPLAY "PAYMENTS READ: " WS-READ-COUNT
DISPLAY "PAYMENTS APPROVED: " WS-APPROVED-COUNT
DISPLAY "PAYMENTS EXCEPTION: " WS-EXCEPTION-COUNT
DISPLAY "PAYMENTS REJECTED: " WS-REJECTED-COUNT
CLOSE PAYMENT-IN
PAYMENT-APPROVED
PAYMENT-EXCEPTION.
Technically, this may look simple, but architecturally, it solves almost nothing.
The real questions are not about converting the syntax. The real questions are about business meaning, ownership, operational behavior, and downstream impact. Why is the past-due threshold 30 days? Is that a business policy, a regulatory rule, or an old operational habit? Does it apply to all customers, all merchants, all regions, and all payment products? Where does the customer status come from, and who owns it? What does “SUSPENDED” mean in this context? Is it set by another system, and is it updated in real time or by overnight batch? What happens to rejected payments? Are they reported to the customer, written to an exception file, or included in reconciliation? What does “MANUALREV” trigger? Is there a queue, an SLA, or an audit trail? Is the 10,000 limit fixed, configurable, or different by merchant category? Does changing it affect fraud rules, settlement, compliance, or partner contracts?
This is why rewriting the COBOL is not the point. The code is only the visible surface, while the business meaning is underneath it.
In a real system, this logic may be connected to JCL jobs, DB2 tables, VSAM files, copybooks, reports, exception queues, reconciliation files, downstream settlement systems, and manual operations. A simple rewrite may preserve the visible logic while breaking the surrounding business process, and that is the biggest danger.
The architect’s job is not to ask: “Can we rewrite this code”? Of course we can. The better question is: do we understand this rule well enough to move it, expose it, change it, test it, and prove that the business outcome remains correct?
That is the modernization question.
The JCL Job That Executes the COBOL Program
In a mainframe environment, the COBOL program does not usually run by itself the way a command-line utility might run on a developer’s laptop. It is typically executed by a job, often defined in JCL. The JCL describes what program to run, which datasets to use as input and output, where to write system messages, and how the execution should be managed.
A simplified JCL job for the COBOL program above might look like this:
//PAYPOSTJ JOB (ACCT),'PAYMENT POSTING',
// CLASS=A,
// MSGCLASS=X,
// NOTIFY=&SYSUID
//*
//* STEP 1: RUN PAYMENT POSTING PROGRAM
//*
//POSTSTEP EXEC PGM=PAYPOST
//*
//* INPUT PAYMENT FILE
//*
//PAYIN DD DSN=NBPAY.PROD.PAYMENTS.INCOMING,
// DISP=SHR
//*
//* APPROVED PAYMENT OUTPUT FILE
//*
//PAYAPP DD DSN=NBPAY.PROD.PAYMENTS.APPROVED,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(50,10),RLSE),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//*
//* EXCEPTION PAYMENT OUTPUT FILE
//*
//PAYEXC DD DSN=NBPAY.PROD.PAYMENTS.EXCEPTION,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(20,5),RLSE),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//*
//* SYSTEM OUTPUT
//*
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
This job is intentionally simplified, but even here we can see why modernization is not just about the COBOL program. The JCL tells us which dataset is used as input, where approved payments are written, where exception payments are written, how output datasets are allocated, what happens if creation succeeds or fails, and where execution messages go.
In a real system, this job might be one step in a larger batch chain. A previous job may receive or transform the incoming file, a sort step may run before the COBOL program, a DB2 update step may follow, and a downstream job may read the approved payment file and create a settlement file. Another job may read the exception file and create an operations report, while scheduler rules may prevent this job from running until another file arrives, and restart instructions may define what happens if the job fails halfway through processing.
A more realistic batch flow may look like this:
Now imagine rewriting only the COBOL program without understanding the rest of this chain. The new program may produce a slightly different record layout, change how rejected payments are categorized, write output earlier or later, handle rounding differently, produce counters in a different format, or treat empty fields differently. Any one of those differences can break a downstream job, report, reconciliation process, or manual procedure.
That is why the JCL is part of the architecture, the job schedule is part of the architecture, the datasets are part of the architecture, the reports are part of the architecture, and the operational procedures are part of the architecture.
A More Complete JCL Flow With Multiple Steps
To make this even clearer, consider a slightly larger JCL job that first sorts incoming payment records, then runs the COBOL posting program, and then runs a reconciliation program. This is still simplified, but it shows how business processing may be spread across several steps rather than contained in one program.
//PAYRUN JOB (ACCT),'DAILY PAYMENT RUN',
// CLASS=A,
// MSGCLASS=X,
// NOTIFY=&SYSUID
//*
//* STEP 1: SORT INCOMING PAYMENT FILE BY MERCHANT AND PAYMENT ID
//*
//SORTSTEP EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SORTIN DD DSN=NBPAY.PROD.PAYMENTS.INCOMING,
// DISP=SHR
//SORTOUT DD DSN=NBPAY.WORK.PAYMENTS.SORTED,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(50,10),RLSE),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSIN DD *
SORT FIELDS=(11,10,CH,A,21,12,CH,A)
/*
//*
//* STEP 2: RUN PAYMENT POSTING PROGRAM
//*
//POSTSTEP EXEC PGM=PAYPOST,COND=(0,NE,SORTSTEP)
//PAYIN DD DSN=NBPAY.WORK.PAYMENTS.SORTED,
// DISP=SHR
//PAYAPP DD DSN=NBPAY.PROD.PAYMENTS.APPROVED,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(50,10),RLSE),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//PAYEXC DD DSN=NBPAY.PROD.PAYMENTS.EXCEPTION,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(20,5),RLSE),
// DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//*
//* STEP 3: RUN RECONCILIATION PROGRAM
//*
//RECSTEP EXEC PGM=PAYRECON,COND=(0,NE,POSTSTEP)
//PAYIN DD DSN=NBPAY.WORK.PAYMENTS.SORTED,
// DISP=SHR
//PAYAPP DD DSN=NBPAY.PROD.PAYMENTS.APPROVED,
// DISP=SHR
//PAYEXC DD DSN=NBPAY.PROD.PAYMENTS.EXCEPTION,
// DISP=SHR
//REPRPT DD DSN=NBPAY.PROD.REPORTS.PAYRECON,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(5,2),RLSE),
// DCB=(RECFM=FB,LRECL=132,BLKSIZE=0)
//SYSPRINT DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
This example shows why an architect must look beyond the program. The first step sorts the incoming file, the second step runs the payment posting program, and the third step reconciles input, approved output, and exception output. If any of those steps are changed, the business result may change.
The COND parameters also show that job execution can depend on the return code of previous steps. In a real production environment, the scheduler may add another layer of logic around this, including file-arrival triggers, predecessor jobs, calendars, cutoff times, restart rules, and alerting. This means the modernization scope includes not only code, but also execution semantics.
If a team rewrites PAYPOST as a cloud service without understanding SORTSTEP, RECSTEP, dataset layouts, scheduler rules, and reconciliation expectations, the new implementation may be technically correct in isolation and still fail the business process.
Why Rewriting the COBOL Is Not the Point
The COBOL program above can be rewritten quickly, and the JCL can also be translated into a modern pipeline. A cloud-native team could read records from object storage, sort them, process them in a container, write approved and exception outputs, and run reconciliation as another step. Technically, that is feasible.
But modernization is not successful simply because the code was translated. It is successful only if the business outcome remains correct, auditable, maintainable, and easier to evolve.
The architect must understand what the input file represents, who owns the file format, whether the sort order matters, how payment status is interpreted, how exception reasons are consumed, how approved payments flow into settlement, how reconciliation is performed, what return codes mean, how failures are restarted, what reports operations expects, and how finance confirms that money moved correctly.
This is the difference between code conversion and architecture modernization. Code conversion asks whether we can produce equivalent code in another language, while architecture modernization asks whether we understand the capability well enough to improve it safely.
In many cases, the first modernization step may be to leave the COBOL where it is, but document the rules, expose a safe inquiry API, improve job monitoring, create better reconciliation visibility, and build a data pipeline for analytics. Later, once the business capability is understood and tested, selected parts can be refactored, extracted, replatformed, or replaced.
That approach may sound less dramatic than a rewrite, but it is much more likely to protect the business.
The Mainframe May Stay, but the Architecture Must Improve
The conclusion for NorthBridge Payments may not be “move everything off the mainframe,” because that may be unrealistic, unnecessary, or too risky. A better conclusion may be more nuanced.
The company may decide to keep the high-throughput settlement engine on z/OS for now, wrap selected CICS transactions with APIs, improve documentation and job observability, extract rules into a validated catalog, move reporting and analytics data into a cloud platform, refactor the most painful COBOL modules, reduce batch window pressure, identify one bounded capability that can be extracted into a modern service, retire obsolete jobs, and replatform selected workloads only where the business case is strong.
That is a credible modernization strategy because it does not pretend that legacy systems are bad, that cloud automatically solves business complexity, or that AI can magically convert decades of operational knowledge into a perfect modern architecture. Instead, it treats modernization as a controlled architectural process.
The Real Goal
The goal is not to get rid of COBOL as quickly as possible. The goal is to make the payment platform understandable, maintainable, testable, integrable, observable, and easier to evolve.
For NorthBridge Payments, modernization means reducing dependency on undocumented knowledge, making business rules visible, exposing the right capabilities through APIs, shortening change cycles, reducing operational risk, giving cloud analytics and AI teams governed access to data, and preparing for future migration without forcing a dangerous big-bang rewrite.
That is the architecture point of view. A COBOL rewrite changes the language, but a serious modernization program changes the company’s ability to understand, control, and evolve its core business platform.
Discussion Board Coming Soon
We're building a discussion board where you can share your thoughts and connect with other readers. Stay tuned!
Ready for CTO-level Leadership Without a Full-time Hire?
Let's discuss how Fractional CTO support can align your technology, roadmap, and team with the business, unblock delivery, and give you a clear path for the next 12 to 18 months.
Or reach us at: info@sharplogica.com