Integrating with a core that predates JSON
Fixed-width files, nightly batches and a system nobody wants to touch. How to build modern services on top of a core you cannot change.

A great deal of financial software in production predates the conventions everyone now takes for granted. It speaks fixed-width records, or a proprietary socket protocol, or ISO 8583, or it exchanges files on a schedule and considers that an interface. It is frequently the most reliable component in the institution, and the people who understand it are close to retirement.
You will not be replacing it this year. The question is how to build against it without either destabilising it or inheriting its constraints throughout everything new.
The first rule is to put a boundary in front of it and never let anything else past. One integration layer owns every conversation with the core, and exposes a clean interface to everything else. No mobile app, no reporting tool, no third-party product talks to it directly. This costs a little more at the start and it is the difference between eventually replacing the core and never being able to.
The value shows up on the day you migrate. If eleven systems each hold their own connection and their own assumptions about record layouts, replacing the core means changing eleven systems simultaneously. If they all speak to one boundary, you reimplement the boundary and everything upstream is unaffected. Nobody regrets having built this. Plenty of institutions regret not having.
The second rule is to resist letting the core's model leak through. It is tempting to expose its fields as they are, because that is less work. But if your API returns a customer type of 03 and a status flag of Y, then every consumer for the next decade encodes those meanings, and you have simply relocated the legacy rather than contained it. Translate at the boundary. Meaningful names, real dates, explicit currencies, documented enumerations.
The third is to be realistic about what the core can take. These systems were sized for a fixed number of branches making predictable request volumes during business hours. A mobile app changes that shape completely — customers check balances at midnight, and they check them repeatedly. We have seen a new channel take down a core that had run for fifteen years, not through any defect, but because nobody modelled what happens when balance enquiries increase forty-fold.
So cache aggressively for reads, with explicit and honest freshness. Rate-limit at the boundary. And be careful about batch windows: if the core is unavailable or degraded during nightly processing, your services must degrade predictably rather than time out in ways that make customers retry, which is how a slow window becomes an outage.
The fourth is that where the core is batch, you must not pretend it is real-time. If balances update overnight, a customer-facing screen showing a balance as though it were current will generate complaints and, in some markets, regulatory attention. Show what it is: as of last night's close, with pending items listed separately. Customers handle that fine when it is stated. What they do not forgive is a number presented as current that turns out not to be.
The fifth, and the one most often skipped: write down the protocol while someone still remembers it. Undocumented interfaces are common in institutions like this, and the knowledge frequently exists in one person's head. Sit with them. Record the field layouts, the error codes, the retry semantics, the reason for the strange rule about the third character. This is the highest-return work available in these projects and it is invariably deprioritised until the person leaves.
Treat the old system as a supplier with a fixed contract you cannot renegotiate. Wrap it, translate it, protect it from load it was never designed for, and be honest with users about what it can tell them.
Then you can build whatever you like on top — and replace it when you are ready, rather than when it finally fails.