The Banking System is Async

Understand how payments systems work asynchronously under the hood and how to design software systems around it.

Payment systems are rapidly improving over time, but some things stay the same. The way that money moves through the banking system is message-driven and asynchronous. As a software engineer, understanding how this works at the fundamental level can help guide your product design process and help you build better, more robust software.

If you're familiar with interacting with APIs on the internet, you may expect most API-driven services to provide instantaneous operations. Banking payment systems do not work this way.

As software modernizes and software engineers rebuild software that interfaces with the banking system, it's important to understand how banking rails really work and how to design your products around it.

One-Way versus Two-Way Communication

Most developers are familiar with REST APIs – a two-way protocol that always involves a request and response. Think of it as a two-way communication protocol – the receiving server will always provide a response given a properly formatted request.

Bank payments are message-driven, meaning that they are comprised of one-way messages, either to the bank or from the bank. This is fundamentally different than the REST API architectures most developers are used to.

Using ISO20022, the global standard interface for communicating with banks, payment instructions are sent in a Payment Initiation (pain.001) instruction. This is the first message sent to the bank, and there isn't expected to be an immediate response back.

Subsequently, updates to each payment come in two parts – incoming Payment Status Report (pain.002) messages and Cash Management (camt) messages.

Consider a typical REST request versus the flow for sending ACH or even instant RTP payments. In the REST example a response is immediately returned by the server. Payment instructions are fundamentally one-way, message-driven events.

When moving money through the ACH network, one must expect updates over the course of days after the initial instruction. The same technique is true for RTP over a much shorter scale – updates are given in seconds, but in the same message driven fashion.

Do Not Expect a Call Back

Given the event-driven, message-based nature of payments, you shouldn't design a system dependent on a callback from the network in a short-term time horizon. Consider making an API request to send an “instant” payment – the naïve approach here is to block until a payment is cleared. This is fundamentally the wrong approach to interacting with the banking system.

When sending payments to banks, you must work around non-blocking events, even if using real time payments rails.

You Need a State Machine

Given that payment networks are message-based, you must consider having an in-house state machine to manage the lifecycle of payments, regardless of the payment rail you're using. This is one example of a successful state machine in practice.

Storing states is reflective of the lifecycle of an ISO20022 payment instruction as it makes its way through the network. In general, you will find yourself receiving and storing these states in a Payment Status Report message:

  • Accepted
  • Pending
  • AcceptedSettlementCompleted
  • Rejected

Ingesting payment status reports is critical to understanding the state of a payment, and used to track the lifecycle of a payment.

Conclusion

When designing products that involve money sent through banks, it's important to consider that bank payments operate through a lifecycle, and they require designing a system that stores state.

It's also important to understand that ISO20022, the standard interface to send payment instructions, is message-based. To move money using ISO20022, one must send Payment Initiation files and ingest Payment Status Report files, all while keeping track of it's state via a state machine.

When building interfaces against banks, you'll likely be sending instructions via ISO20022. Iso20022.js is the most source library to interface with banks. If you're interfacing with the banking system and have any questions, please reach out to us and we'd love to chat.