MarblePay follows a modular monolith architecture for MVP/V1, with clear service boundaries that can be extracted into microservices as scale demands.
┌─────────────────────────────────────────────────────────────────┐
│ Client Layer │
├─────────────────────────────────────────────────────────────────┤
│ Merchant Dashboard │ Hosted Checkout │ Drop-in Widget │
│ (Next.js) │ (Next.js) │ (React/Vanilla) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ API Gateway / BFF │
│ (NestJS + Express) │
├─────────────────────────────────────────────────────────────────┤
│ Authentication │ Rate Limiting │ Request Validation │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Core Services Layer │
├──────────────────┬──────────────────┬──────────────────┬─────────┤
│ Auth Service │ Merchant Service │ Payment Service │ Wallet │
│ │ │ │ Service │
├──────────────────┼──────────────────┼──────────────────┼─────────┤
│ Quote Service │ Settlement Srv │ Webhook Service │Compliance│
│ │ │ │ Service │
├──────────────────┼──────────────────┼──────────────────┼─────────┤
│ Ledger Service │ Risk Service │ Notification Srv │ Admin │
└──────────────────┴──────────────────┴──────────────────┴─────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Infrastructure Layer │
├──────────────────┬──────────────────┬──────────────────┬─────────┤
│ PostgreSQL │ Redis │ S3/Object Store │ Kafka │
│ (Primary DB) │ (Cache/Queue) │ (KYC docs) │ (Events)│
└──────────────────┴──────────────────┴──────────────────┴─────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ External Services │
├──────────────────┬──────────────────┬──────────────────┬─────────┤
│ Blockchain │ Custody │ Compliance │ Fiat │
│ RPC Providers │ (Fireblocks) │ (TRM/Chainalysis│ Rails │
│ (Infura/Alchemy)│ │ Smile ID) │(YellowC)│
└──────────────────┴──────────────────┴──────────────────┴─────────┘
Responsibility: Authentication, authorization, session management
Key Features:
- Merchant login (email/password, 2FA)
- API key generation & rotation
- JWT token issuance & validation
- Role-based access control (RBAC)
- Device fingerprinting
- Session management
Tech Stack:
- Passport.js for strategies
- bcrypt for password hashing
- JWT for tokens
- Redis for session store
Database Schema:
users (id, email, password_hash, role, 2fa_secret, created_at)
api_keys (id, user_id, key_hash, scopes, expires_at)
sessions (id, user_id, token, device_fingerprint, ip, expires_at)Responsibility: Merchant onboarding, KYB/KYC, profile management
Key Features:
- Merchant registration flow
- KYB/KYC document upload & verification
- Beneficial owner management
- Business profile & settings
- Bank account linking (for NGN settlements)
- Compliance status tracking
External Integrations:
- Smile Identity, Dojah, VerifyMe (KYC)
- Sanctions screening (Chainalysis)
Database Schema:
merchants (id, business_name, email, country, kyc_status, sec_license_no)
beneficial_owners (id, merchant_id, name, bvn, kyc_status)
kyc_documents (id, merchant_id, doc_type, s3_url, verified_at)
merchant_settings (id, merchant_id, settlement_currency, webhook_url)Responsibility: Checkout sessions, payment processing, status tracking
Key Features:
- Create checkout session
- Generate unique deposit address
- Monitor blockchain for incoming transactions
- Handle confirmations (pending → confirmed → settled)
- Underpay/overpay/late payment detection
- Refund processing
- Partial captures
Flow:
1. Merchant creates checkout session via API
2. System generates unique address (via Wallet Service)
3. System locks quote (via Quote Service) with expiry
4. Customer sends crypto to address
5. System detects transaction (blockchain watcher)
6. System validates amount, chain, confirmations
7. System triggers webhook (payment.confirmed)
8. System initiates settlement (Settlement Service)
Database Schema:
checkout_sessions (id, merchant_id, amount, currency, chain, status, expires_at)
payments (id, session_id, tx_hash, chain, amount, confirmations, status)
refunds (id, payment_id, amount, refund_address, status, tx_hash)Responsibility: Custody, address generation, transaction signing
Key Features:
- Hot wallet management (MPC/HSM)
- Cold storage integration
- Address generation per session
- Transaction broadcasting
- Balance tracking
- Multi-sig support (V2)
Security:
- Private keys never stored in DB
- KMS-backed key storage (AWS KMS, GCP Secret Manager)
- Fireblocks MPC integration
- Address whitelisting
Database Schema:
wallets (id, chain, address, type, balance, cold_storage)
transactions (id, wallet_id, tx_hash, from_address, to_address, amount, status)
address_pool (id, chain, address, used, assigned_to_session_id)Responsibility: Real-time pricing, FX rates, gas estimation
Key Features:
- Fetch real-time crypto prices (CoinGecko, CoinMarketCap)
- Calculate gas fees (Infura Gas API, Etherscan)
- Apply spread + platform fee
- Lock quote with expiry (stored in Redis)
- Multi-chain support
Pricing Formula:
Total = (Amount_NGN / Crypto_Price) + Gas_Fee + Spread + Platform_Fee
Caching:
- Redis cache with 10-30s TTL for prices
- Gas prices updated every block (~12s for Ethereum)
Database Schema:
quotes (id, session_id, amount_fiat, amount_crypto, rate, gas_fee, expires_at)Responsibility: Payouts to merchants (crypto or fiat)
Key Features:
- Crypto settlements (same-chain, same-asset)
- USDC conversion before payout
- NGN settlements via Yellow Card / Transak
- Batch processing for efficiency
- Settlement scheduling (instant, daily, weekly)
Flow:
1. Payment confirmed
2. Check merchant's settlement preference (crypto/fiat)
3. If crypto: Transfer to merchant wallet
4. If fiat: Convert via partner (Yellow Card) → bank transfer
5. Record in ledger
6. Send webhook (settlement.completed)
Database Schema:
settlements (id, merchant_id, amount, currency, method, status, initiated_at)
payouts (id, settlement_id, tx_hash, destination_address, status)Responsibility: Event delivery, retries, signature verification
Key Features:
- Event queue (Redis Streams or Kafka)
- HMAC-SHA256 signature generation
- Exponential backoff retry (1m, 5m, 15m, 1h, 6h)
- Webhook logs & delivery status
- Test mode webhooks
Events:
checkout.createdpayment.pendingpayment.confirmedpayment.expiredrefund.processedsettlement.completed
Signature Header:
X-Signature: sha256=<hmac_hex>
X-Timestamp: <unix_timestamp>
Database Schema:
webhook_events (id, merchant_id, event_type, payload, signature, attempts, delivered_at)
webhook_logs (id, event_id, status_code, response, attempted_at)Responsibility: AML screening, Travel Rule, risk scoring
Key Features:
- Pre-transaction address screening (Chainalysis KYT, TRM)
- Sanctions list checking (OFAC, UN, EU)
- Travel Rule data collection & transmission
- SAR/STR workflow
- Case management for flagged transactions
Integrations:
- Chainalysis KYT API
- TRM Labs Travel Rule API
- Internal risk scoring model
Flow:
1. Before processing payment: Screen source address
2. Before settlement: Screen destination address
3. If Travel Rule threshold met: Collect beneficiary data
4. If high-risk: Flag for manual review
5. If sanctioned: Reject transaction
Database Schema:
screening_results (id, transaction_id, address, risk_score, sanctions_hit, reviewed_at)
travel_rule_data (id, transaction_id, originator_data, beneficiary_data)
compliance_cases (id, transaction_id, case_type, status, assigned_to, resolved_at)Responsibility: Double-entry bookkeeping, reconciliation
Key Features:
- Record all asset movements
- Track fees, spreads, PnL
- Multi-currency balances
- Reconciliation with on-chain data
- Audit logs
- Financial reports
Double-Entry Example:
Payment received (100 USDC):
Debit: Hot Wallet (Asset) +100 USDC
Credit: Merchant Payable (Liability) +100 USDC
Settlement to merchant:
Debit: Merchant Payable -100 USDC
Credit: Hot Wallet -100 USDC
Database Schema:
ledger_entries (id, account_id, debit, credit, currency, reference_id, created_at)
accounts (id, account_type, currency, balance)Responsibility: Fraud detection, velocity checks, anomaly detection
Key Features:
- Velocity limits (e.g., max 5 transactions per hour per merchant)
- Geolocation checks
- Device fingerprinting
- Behavioral analysis (V2: ML-based)
- Blacklist/whitelist management
Rules Engine:
rules:
- name: "High-value transaction"
condition: amount > 50000 USD
action: manual_review
- name: "Velocity breach"
condition: transactions_per_hour > 10
action: rate_limit
- name: "Sanctioned country"
condition: ip_country in [sanctioned_list]
action: rejectDatabase Schema:
risk_rules (id, rule_name, condition, action, active)
risk_alerts (id, transaction_id, rule_id, severity, reviewed_at)Primary: Infura, Alchemy, QuickNode
Fallback Strategy:
- Try primary provider
- If fails, fallback to secondary
- If both fail, use own node (future)
Architecture:
Blockchain Watcher (Worker Process)
↓
Poll RPC every 5s for new blocks
↓
Check addresses in our pool for incoming txs
↓
If found: Update payment status, trigger webhook
Implementation:
- Use
eth_getLogsfor Ethereum/Base - Use
getSignaturesForAddressfor Solana - Store last processed block in Redis
- Pre-fund hot wallet with native tokens (ETH, SOL)
- Monitor gas prices, use EIP-1559 for Ethereum
- Set max gas price limits to avoid overpaying
Customer → Checkout Page → API: Create Session
↓
Generate Address (Wallet Service)
↓
Lock Quote (Quote Service)
↓
Return: {address, amount, expiry}
↓
Customer → Wallet → Send Crypto → Blockchain
↓
Watcher detects tx
↓
Screen address (Compliance)
↓
Update payment status
↓
Trigger webhook
↓
Initiate settlement (Settlement Service)
↓
Record in ledger
- Perimeter: WAF (Cloudflare), DDoS protection
- API: Rate limiting, API key validation, HMAC signatures
- Application: Input validation, SQL injection prevention, XSS protection
- Data: Encryption at rest (AES-256), in transit (TLS 1.3)
- Keys: KMS-managed, rotated every 90 days
- Monitoring: Intrusion detection, anomaly alerts
- Hot Wallet Keys: AWS KMS / GCP Secret Manager
- API Keys: Hashed with bcrypt, never stored plain
- Webhook Secrets: Per-merchant, rotatable
- Database: Encrypted at rest, SSL connections
- Single monolith application
- Single PostgreSQL instance
- Redis single node
- 2-4 backend servers (load balanced)
- Extract Payment + Wallet services
- PostgreSQL read replicas
- Redis cluster
- Kafka for event streaming
- 10-20 backend servers
- Full microservices architecture
- Multi-region deployment
- Sharded PostgreSQL
- Dedicated blockchain node infrastructure
- Auto-scaling based on load
- Structured JSON logs (Winston)
- Per-request trace ID
- Sensitive data redaction
- Centralized logging (Elasticsearch)
- Request latency (p50, p95, p99)
- Error rates
- Payment success rate
- Webhook delivery rate
- Blockchain confirmation times
- PagerDuty for critical alerts
- Slack for warnings
- Email for info
- Grafana: System health, API metrics
- Custom: Payment funnel, revenue, settlements
- PostgreSQL: Daily full backup + WAL archiving
- Redis: RDB snapshots every 6 hours
- S3: Versioning enabled for KYC documents
- RTO (Recovery Time): < 4 hours
- RPO (Recovery Point): < 1 hour
- Multi-sig on high-value wallets
- Daily balance checks
- Automated transfer to cold storage > threshold
- Alert on unexpected withdrawals
| Component | Technology |
|---|---|
| Frontend | Next.js 14, TypeScript, Tailwind |
| Backend | NestJS, Node.js, TypeScript |
| Database | PostgreSQL 15+ |
| Cache/Queue | Redis 7+ |
| Event Stream | Kafka (V2) / Redis Streams (MVP) |
| Blockchain RPC | Infura, Alchemy, QuickNode |
| Custody | Fireblocks / BitGo |
| KYC | Smile Identity, Dojah |
| Compliance | Chainalysis, TRM Labs |
| Fiat Rails | Yellow Card, Transak |
| Observability | Prometheus, Grafana, Sentry |
| Cloud | AWS / GCP |
| CDN | Cloudflare |
Next: API Reference | Webhooks Guide