Building Payment Processing: What I Learned Implementing ISO 8583 and 20022 at BVNK

Building Payment Processing: What I Learned Implementing ISO 8583 and 20022 at BVNK

I needed to implement dual payment protocol support whilst building BVNK's core banking system. Not the kind of problem most developers face, but when you're building financial infrastructure from scratch, you quickly discover that payment processing isn't just about API calls to Stripe.

We needed both ISO 8583 for traditional card processing and ISO 20022 for modern payment messaging across the broader financial system. Table stakes for any serious fintech platform, but the devil was in the implementation details. Most developers never touch these standards directly - they're hidden behind payment processors and banking APIs. But when you're building the infrastructure itself, you get to see how the sausage is really made.

Here's what I learned about payment standards, and why even "standard" implementations aren't actually standard.

What Actually Is an ISO?

From a builder's perspective, an Independent Sales Organisation (ISO) is essentially a middleman between merchants and payment processors. ISOs in credit card processing handle the complexity of integrating with card networks whilst taking on compliance and risk responsibilities.

The business model is straightforward: merchant services ISO programs typically offer revenue share on transaction fees, ranging from 10-100 basis points depending on volume and risk profile. But becoming an ISO for merchant services isn't trivial - you're looking at £15-20K registration fees with card networks, PCI DSS compliance, and usually £1M+ in financial backing.

At BVNK, we evaluated becoming a payment processing ISO versus partnering with existing processors. The decision hinged on control versus complexity. Building our own ISO capabilities meant owning the entire payment flow, but it also meant implementing the message standards that power everything.

That's where ISO 8583 and ISO 20022 come in - the protocols that actually move money around the global financial system.

The Message Standards That Power Everything

In 2024, you need both protocols if you're serious about payment processing. It's not an either-or decision.

ISO 8583 handles traditional card transactions. It's binary, efficient, and every card network speaks it. The format is compact - perfect for high-frequency card processing where milliseconds matter.

ISO 20022 is the new global messaging standard replacing older formats across all payment types. XML-based with rich data structures, it's being adopted by SWIFT, FedNow, and central banks worldwide. More verbose than 8583, but far more flexible for complex financial data and richer transaction information.

Here's a simplified Go struct for handling ISO 8583 messages:

type ISO8583Message struct {
    MTI        string // Message Type Indicator
    PAN        string // Primary Account Number (masked)
    Amount     int64  // Transaction amount in smallest currency unit
    MerchantID string
    TerminalID string
    ResponseCode string
    // ... dozens more fields depending on message type
}

func (m *ISO8583Message) Validate() error {
    if len(m.MTI) != 4 {
        return errors.New("invalid MTI length")
    }
    // Validation logic here
    return nil
}

ISO 20022 is completely different - structured XML with proper schemas:

type PaymentInstruction struct {
    XMLName xml.Name `xml:"PmtInf"`
    PmtInfId string  `xml:"PmtInfId"`
    PmtMtd   string  `xml:"PmtMtd"`
    ReqdExctnDt string `xml:"ReqdExctnDt"`
    // Nested structures for debtor, creditor, etc.
}

The performance implications are significant. Binary 8583 messages are typically 100-500 bytes. ISO 20022 XML can easily hit 5-10KB for complex transactions. When you're processing thousands of messages per second, that difference matters.

But here's where it gets interesting - implementation reality is far messier than the standards suggest.

Integration Challenges I Actually Hit

The biggest challenge wasn't performance or message structure. It was the fact that "standard" implementations aren't actually standard in ISO merchant processing.

We discovered this whilst implementing ISO 20022. Different institutions had their own interpretations of field requirements, message structure, and validation rules. What should have been a straightforward schema validation became a collection of edge cases and workarounds.

Our team built a comprehensive ISO 8583 package covering the 1987, 1993, and 2003 versions. As a merchant ISO implementer, he had to reverse-engineer implementations because the official documentation costs thousands of pounds, and even then, real-world usage differed from the specs.

// Circuit breaker pattern for handling flaky message processing
type MessageProcessor struct {
    iso8583Handler  *ISO8583Handler
    iso20022Handler *ISO20022Handler
    circuitBreaker  *CircuitBreaker
}

func (mp *MessageProcessor) ProcessMessage(data []byte) error {
    return mp.circuitBreaker.Execute(func() error {
        // Detect message format
        if isBinary(data) {
            return mp.iso8583Handler.Process(data)
        }
        return mp.iso20022Handler.Process(data)
    })
}

Database consistency across protocols required careful transaction management. You can't assume both message types will have the same failure modes or retry semantics.

The testing complexity was brutal. We built mock message generators and validators, then collected examples from different implementations to ensure compatibility. Each "standard" implementation had its own quirks.

Similar to what I discovered with mocking Redis and Kafka in Go, testing distributed payment systems requires thinking beyond happy path scenarios. Message replay, partial failures, and network timeouts all need handling.

The 2024-2025 Reality Check

FedNow's adoption is driving ISO 20022 implementation across US financial institutions. Over 900 institutions are now connected, processing 1.5 million transactions in Q4 2024 alone. This isn't optional anymore - it's infrastructure.

The credit card ISO market reality is consolidation. Fiserv, FIS, and Global Payments handle the majority of ISO transactions - roughly £52 trillion annually flows through these systems. Digital wallets add another layer of complexity, now representing 53% of online transactions.

For builders, this means the barrier to entry keeps rising. The technical implementation is just table stakes - you also need the regulatory compliance, financial backing, and industry relationships.

BVNK's dual protocol approach was forward-thinking. Most companies are scrambling to add ISO 20022 support to existing 8583 infrastructure. Building both from the ground up meant cleaner architecture and fewer compromises.

What Surprised Me Most

Standards that aren't standard. I expected payment protocols to be like HTTP - well-defined, widely implemented, consistent across systems.

The reality is messier. Through conversations with banks and financial integrators in Africa, I learned about institutions that couldn't communicate directly despite "following" the same standards. The implementations differed enough that a middleman company emerged purely to translate between different interpretations of the same protocol.

This company exists solely to transform messages between banks that should theoretically be compatible. It's a problem that shouldn't exist, but it's immensely lucrative because the standards reality doesn't match the standards documentation.

Implementation Patterns That Worked

After building both protocols, here are the patterns that proved reliable:

Message Validation Strategy:

  • Strict schema validation for ISO 20022
  • Field-by-field validation for ISO 8583
  • Configurable validation rules per institution

Error Handling:

  • Circuit breakers for external system calls
  • Exponential backoff with jitter
  • Dead letter queues for failed messages

Performance Optimisation:

The security requirements go beyond PCI DSS. Message signing, replay protection, and constant-time comparisons for sensitive operations are essential.

What I'd Build Differently Now

Honestly, I'd probably follow the same approach. Building custom Go libraries for both standards gave us complete control over the implementation. The alternative - integrating with existing libraries - would have meant accepting someone else's interpretation of the standards.

The key insight was treating standards as guidelines rather than gospel. Every integration required testing against the specific institution's implementation, not just the documented standard.

For teams considering similar implementations: budget extra time for the "standards aren't standard" reality. Your test suite needs to validate against real-world implementations, not just the specification documents.

Understanding how to become an ISO for merchant services isn't just about the business requirements - it's about navigating the technical complexity of multiple protocol implementations that don't quite match their documentation.

The Real Lesson

Payment processing standards exist in theory. In practice, every implementation is slightly different, and those differences compound across the entire financial system.

If you're building payment infrastructure, plan for this reality. Standards documentation gets you 80% there - the final 20% comes from testing against actual systems and handling the edge cases that nobody documents.

The good news? Once you understand this, you can build more robust systems than teams who assume standards are actually standard. And occasionally, you might even spot opportunities to build the middleware that shouldn't need to exist.


Need help with your business?

Enjoyed this post? I help companies navigate AI implementation, fintech architecture, and technical strategy. Whether you're scaling engineering teams or building AI-powered products, I'd love to discuss your challenges.

Learn more about how I can support you.

Get practical insights weekly

Real solutions to real problems. No fluff, just production-ready code and workflows that work.
You've successfully subscribed to Kyle Redelinghuys
Great! Next, complete checkout to get full access to all premium content.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.