multi-currency-payment-platform@sutraq:~/case-study
Financial Technology 12 months 2019-2020

Multi-Currency Payment Platform

@ Sutraq — JavaScript Developer

Building a secure, compliant payment infrastructure for cross-border commerce in the Middle East

$10M+ Monthly Volume
15+ Currencies
99.99% Uptime

$ cat PROBLEM.md

Monolith Couldn't Scale for Multi-Currency Operations

Sutraq's original payment platform was a monolithic Node.js application that struggled with the complexity of multi-currency transactions, real-time exchange rates, and varying regulatory requirements across Middle Eastern and European markets. Deployment fear, compliance audits, and performance bottlenecks were blocking growth.

Key Challenges:

  • 🔴 Single database becoming a bottleneck for transaction throughput
  • 🔴 Currency conversion logic scattered across codebase with inconsistencies
  • 🔴 Every deployment risked the entire payment flow
  • 🔴 PCI-DSS audit found issues with shared infrastructure components

$ cat SOLUTION.md

Domain-Driven Microservices with PCI-Compliant Architecture

We decomposed the monolith into domain-focused microservices with clear boundaries, implementing a PCI-compliant architecture that isolated sensitive payment data.

Technical Approach:

1
Domain-Driven Decomposition

Split into bounded contexts: Payments, Currencies, Users, Compliance, and Reporting. Each service owns its data and business logic.

2
PCI-Compliant Card Data Vault

Isolated card handling into a separate, hardened service with its own infrastructure. Main services never touch raw card numbers.

3
Real-Time Currency Engine

Dedicated service managing exchange rates from multiple providers, handling rate locking, and calculating conversion with transparent fees.

4
Event Sourcing for Audit Trail

All financial transactions stored as immutable events, providing complete audit trail for regulators and dispute resolution.

$ cat tech-stack.json

🚀 Core Technologies

Node.js / Express

Microservices runtime

Why: High I/O throughput for payment processing, large ecosystem for financial integrations

PostgreSQL

Transactional data with ACID guarantees

Why: Battle-tested for financial applications, excellent consistency model

RabbitMQ

Inter-service messaging

Why: Reliable message delivery critical for payment workflows

🔧 Supporting Technologies

Redis MongoDB Stripe / PayFort

☁️ Infrastructure

AWS (ECS, RDS, ElastiCache) Docker Vault by HashiCorp

$ cat ARCHITECTURE.md

The platform uses domain-driven microservices with clear boundaries:

1
2
3
4
5
Client → API Gateway → Payment Service → Card Vault (PCI Zone)
             ↓               ↓                ↓
        Auth Service    Currency Svc    Payment Gateway
             ↓               ↓                ↓
        User Service    Rate Provider   Transaction Log

System Components:

API Gateway

Authentication, rate limiting, and request routing

Payment Service

Orchestrates payment workflows without touching card data

Card Vault Service

PCI-compliant isolated service for card tokenization

Currency Service

Real-time rates, conversion, and fee calculation

$ man implementation-details

Designing the Card Vault

PCI-DSS compliance required isolating all cardholder data:

Architectural Decisions:

  • Separate VPC with no internet access
  • Dedicated RDS instance with encryption at rest
  • All access through private API with mTLS
  • No logs containing card numbers

Tokenization Flow:

  1. Client submits card to Card Vault directly (bypassing main services)
  2. Card Vault validates, encrypts, and returns token
  3. Main services only ever see tokens
  4. Payment execution sends token to Card Vault, which calls gateway
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// Card Vault - Token generation
async tokenize(cardData) {
  // Validate card format
  if (!luhnCheck(cardData.number)) {
    throw new ValidationError('Invalid card number');
  }
  
  // Encrypt with hardware security module
  const encrypted = await hsm.encrypt(cardData);
  
  // Store encrypted data
  const token = generateToken();
  await cardStore.save(token, encrypted);
  
  // Return token (never the card)
  return { token, last4: cardData.number.slice(-4) };
}

Real-Time Currency Engine

Multi-currency support required a sophisticated rate management system:

Rate Aggregation:

  • Multiple rate providers (XE, Fixer.io, bank feeds)
  • Weighted average with outlier detection
  • Failover when primary provider is down

Rate Locking:

  • Rates locked at transaction initiation
  • 15-minute lock window for checkout completion
  • Margin calculation with transparent display
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class CurrencyService {
  async getRate(from, to, amount) {
    // Check cache first
    const cached = await redis.get(`rate:${from}:${to}`);
    if (cached && !this.isStale(cached)) {
      return this.applyMargin(cached);
    }
    
    // Fetch from providers with failover
    const rate = await this.fetchWithFailover([
      () => xe.getRate(from, to),
      () => fixer.getRate(from, to),
      () => bankFeed.getRate(from, to)
    ]);
    
    // Cache for 60 seconds
    await redis.setex(`rate:${from}:${to}`, 60, rate);
    
    return this.applyMargin(rate);
  }
}

$ echo $RESULTS

PCI-DSS Compliant Platform Processing $10M+ Monthly

$10M+ Monthly Volume Processing cross-border payments
99.99% Uptime Critical for payment reliability
15+ Currencies Supporting Middle East and European markets
<200ms Payment Latency P95 for complete payment flow

Additional Outcomes:

  • Passed PCI-DSS Level 1 audit with minimal findings
  • Deployment frequency increased from monthly to daily
  • Currency conversion disputes reduced by 90% with transparent fee display

$ cat LESSONS_LEARNED.md

PCI Compliance Drives Good Architecture

The requirement to isolate card data forced us to create cleaner service boundaries. What seemed like a constraint became a design improvement.

Currency is Harder Than It Looks

Rate volatility, provider failover, and fee transparency created more complexity than the actual payment flow. We should have started with the Currency Service.

Event Sourcing is Worth the Investment for Finance

The ability to replay and audit every transaction proved invaluable for compliance and dispute resolution. The upfront complexity paid off.

$ cat README.md

Want Similar Results?

Let's discuss how I can help solve your engineering challenges.