Transaction codes as a way of abstracting accounting

by Michael Parsons

In this post, we’ll discuss why transaction lifecycles are so complex, and how we can encapsulate these essential parts of accounting into API calls called Transaction Codes (AKA tran codes).

If you are a developer or product leader who is building systems that support money movement, you can think of tran codes as a way to codify complex accounting flows as a one time operation, allowing your developer teams to reuse these codes on their way to building delightful features in the product vs reinventing accounting. With this framework, you can abstract accounting to build a unified core system capable of supporting any payment instrument, vendor, or product.

Introduction: When good accounting systems go bad

It is common when building a financial system to design accounting based on your vendor or current product fund flow. As additional services and integrations are required—such as orchestration for ACH, card processing, foreign exchange, security tracking—the need for a unified accounting system becomes an emergent issue that organizations typically aren’t prepared to deal with.

What can start as a simple immutable “transaction log” ledger in Postgres to track balances with a card issuer can quickly require custom and complex accounting work as new features are added, such as:

  • Custom logic for the fee structure across every transaction
  • A new instant payout feature that requires a new vendor integration
  • Showing the current customer balance in the application
  • Tracking payments flowing into an FBO account and initiate payments flowing out
  • Tracking all customer balances and activity virtually (payments, fees, returns, etc.) across multiple accounts

While customers may not experience bugs in the system, that’s only because there have been many hours spent making real time decisions to build (and re-build) ledgers or shadow ledgers to rectify the numbers and make sure the balances roll up correctly. The engineering and finance teams typically see this accounting progression as a hellish, barren landscape of reconciliation.

A model to decouple the ledger from accounting rules: what does it get you?

In 2013, when we were building the first neobank called Simple, we too found ourselves encountering complex accounting requirements which resulted in disparate ledgers across our card issuers and banking partners, all acting as immutable transaction logs to reconcile with the third parties. As we looked to bring services in-house, it became clear we would need a core ledger and accounting system to support all the products and features our customers wanted while guaranteeing accounting correctness. With this change, we’d be able to get out of the reconciliation game to become a core system of record.

When we made the decision to bring card processing in-house, we partnered with Bancorp Bank to integrate ISO8583 and build our own issuer / processor. We learned a lot about how the bank operates across their accounting core system, but one of the key concepts was an introduction to Transaction Codes. These codes identify the type of transaction (such as a card swipe or check deposit) and determine the type of detailed information that will be entered for that transaction which could later be used to reconcile ledger entries. We learned to conceptualize tran codes as functions which define how a transaction acts upon the ledger.

We used tran codes to encode the basic patterns for a type of transaction as a predictable and repeatable formula which enabled us to come up with other outputs, such as how to compute fees in relation to the transaction. Then it evolved to grouping together authorizations, settlements, and adjustments for card processing, allowing different codes to operate at different layers of the balance stack.

As we leaned into the idea that tran codes could represent all different kinds of transactions in a life cycle, it coalesced with our vision that any engineering individual or team should be able to easily stand up a single core accounting system to manage all the services upon the inception of their product, alleviating accounting complexities and the undifferentiated heavy lifting that plagues fintechs.

Transaction codes implemented as a library of functions

The typical accounting workflow includes identifying the A to B progression for how money flows between a vendor or a payment instrument.

So why do engineering teams repetitively build out funds flows?

The accounting models and tools simply haven’t existed until today. It is common that separate engineering teams build funds flows simultaneously to support a new vendor integration or a new financial feature. The flow of money will vary across these two efforts, and it becomes standard practice to have multiple engineers inventing new accounting designs for each outcome.

But what if developers didn’t have to build out a new accounting system for every product or feature?

What if the funds flow identification process could also create the logic to record that money moves from A to B?, and as a result C and D occurs.

When a tran code library is built out to map transactional activity, it creates a model for how money is moved across accounts. Example activities where a tran code would be issued include

TranCodeDescriptionTypes of Entries Written
WIRE_TRANSFERBank-to-bank wire transferWIRE_OUTGOING_DR, WIRE_INCOMING_CR
CARD_HOLD_CANCELCard hold cancellationCARD_HOLD_CANCEL_DR, CARD_HOLD_CANCEL_CR
DEPOSITBank depositDEPOSIT_DR, DEPOSIT_CR
BILL_PAYMENTBill paymentBILL_PAYMENT_DR, BILL_PAYMENT_CR

With a tran code library, accounting becomes the “heliocentric” model of finance.

What this means is you no longer have to listen to your vendors and replicate their view of accounting. It is now possible to build your product accounting requirements into the system, and have third party systems react to executed workflows — such as making a payment and all the retries and idempotency operations that have to occur— which keeps your accounting system the center of the universe as vendors become commodified, allowing you to more easily switch and lower those costs.

Creating a new competency across engineering and finance teams

Now that we understand the value of a tran code library, who are the responsible parties involved in creating it?

Conway’s law suggests that companies will design systems that mirror their internal communication patterns. What we see a lot are scenarios where the engineering team and the finance team have no line of communication at all. Sometimes the line of communication is through the data team responsible for creating the analytics system the finance team uses. Twisp aims to bridge this gap.

The owners of building the tran code library will create a communication competency across engineering and finance teams. The ideal workflow happens when the finance team designs the funds flow and secures the banking accounts, working hand in hand with a lead engineer to identify all the scenarios where a transaction will occur and to align on the correct way to represent the transactions and accounts recorded. They build a tran code that encapsulates that information so that when transaction X happens, entries of type Y are written, and accounts A & B get debited and credited. There is a clear process that bridges the communication lines across engineering and finance teams.

What this competency allows is a systematic approach to identifying the transaction lifecycle for both the finance and developers teams to work off of. The remaining developers do not need to reinvent accounting for every financial product or learn double-entry accounting.

Once the transaction code library is built, the engineering teams no longer have to care about how the accounting is done or what settlement accounts and fee accounts are collected. In this way, tran codes encapsulate the accounting knowledge with the people who know it best and enable the engineers to build differentiated products with less potential for critical error.

Real world use cases for transaction codes

One of my many joys at Simple was learning all about ISO8583 and how dual message and single message transactions life cycles and adjustments work. Coming from that experience, it was clear that there had to be a way to unify the abstraction of handling card transactions via tran code to identify the various card swipe life cycle across

  • Holds
  • Hold adjustments
  • Hold voids
  • Clearing settlements
  • Returns
  • Balance inquiry

With this library of card processing tran codes, you can represent transactions across any card issuing vendor. This enables you to start thinking about card processing at a higher level to pick the right vendor for your business rather than building a ledger tailored to the vendor’s money movement.

Conclusion: Tran codes are a welcome alternative to an accounting rebuild

By building a tran code library through a new communication competency, designing new fund flows for every product will no longer take up the hundreds of hours required to map money movement across internal and external systems.

When we think of the complex technical and operational problems that engineering teams face when building ledger systems, we firmly believe that these systems are not the differentiating investment or competitive advantage, and it’s not something that all engineering teams need to build themselves, over and over again.

Tran codes enable core ledger systems to operate at scale without sacrificing engineer productivity, making your accounting system the center of the universe.

To learn more about how to get your transaction code library set up on Twisp, book a demo.