Architecture Overview
OpenPay is composed of 10+ microservices connected through NATS JetStream event streams. Every component is open source, containerized with Docker, and designed for horizontal scalability.
Architectural Principles
Microservices
Each service has a single responsibility and can be scaled independently.
Event-Driven
Services communicate asynchronously through NATS JetStream — no blocking calls.
Provider-Agnostic
Hyperswitch routes to 100+ processors. Switch providers without code changes.
Self-Healing
Health checks, automatic restarts, and dead-letter queues for fault tolerance.
System Architecture Diagram
┌─────────────────────────────────┐
│ Internet │
└────────────┬──────────┬─────────┘
│ │
┌──────▼──────┐ │
│ Traefik │ │ Processor
│ (Reverse │ │ Webhooks
│ Proxy) │ │
└──────┬──────┘ │
│ │
┌───────────────────────────┼──────────┼──────────┐
│ │ │ │
│ ┌──────▼──────┐ │ │
│ │ Hyperswitch │ │ │
│ │(Rust, 8081) │ │ │
│ └──────┬──────┘ │ │
│ │ │ │
│ ┌──────▼──────────────────┐ │
│ │ NATS JetStream │ │
│ │ (ports 4222, 8222) │ │
│ │ PAYMENT_EVENTS · DLQ │ │
│ └────┬────┬────┬────┬─────┘ │
│ │ │ │ │ │
│ ┌────────────────────┘ │ │ └─────┐ │
│ │ ┌──────┘ └──────┐ │ │
│ ▼ ▼ ▼ │ │
┌──────┴────────┐ ┌────────────────┐ ┌────────────┐ │
│ Kill Bill │ │ Tazama Rule │ │ NATS-KB │ │
│ (Java, 8082) │ │ Exec (Go,8084)│ │ Bridge │ │
│ Subscriptions│ │ Fraud Rules │ │ (Go) │ │
└───────┬───────┘ └───────┬────────┘ └─────┬──────┘ │
│ │ │ │
▼ ▼ ▼ │
┌─────────────────────────────────────────────────────┐ │
│ PostgreSQL + Redis + NATS │ │
│ (Data Layer — Docker internal only) │ │
└─────────────────────────────────────────────────────┘ │
┌────────────────────┐ ┌────────────────────┐
│ Tazama Rule Studio │ │ Case Management │
│ (Web UI, 3000) │ │ (Web UI, 3001) │
│ Rule Authoring │ │ Alert Review │
└────────────────────┘ └────────────────────┘
All internal services communicate over the Docker bridge network. Only Traefik (ports 80/443) is exposed to the internet.
Payment Event Flow
CUSTOMER HYPERSWITCH NATS TAZAMA YOUR APP
│ │ │ │ │
│ POST /payments │ │ │ │
├────────────────────────────► │ │ │
│ │ │ │ │
│ ├── payments.pending ────►│ │ │
│ │ ├── fraud check ──────────►│ │
│ │ │ │ │
│ │◄── risk_score ──────────┤ │ │
│ │ │ │ │
│ │── Connector request ──► (Payment Processor) │ │
│◄── payment response ───────┤ │ │ │
│ │ │ │ │
│ ├── payments.completed ──►│ │ │
│ │ ├── webhook ────────────────────────────────────►│
│ │ │ │ │
│ │ ├── invoice request ──► Kill Bill │
│ │ │ │ │
│ (or) │ │ │ │
│ ├── payments.failed ─────►│ │ │
│ │ ├── webhook ────────────────────────────────────►│
│ │ │ │ │
│ (on error) │ │ │ │
│ │ ├── dlq.event ───────────► (Investigate) │
Service Communication Matrix
| Service | Language | Port | Storage | Pub/Sub |
|---|---|---|---|---|
| Traefik | Go | 80, 443, 8080 | — | — |
| Hyperswitch | Rust | 8081 | PostgreSQL, Redis | NATS (publish) |
| Kill Bill | Java | 8082 | PostgreSQL | NATS (consume) |
| NATS-KB Bridge | Go | — | — | NATS (both) |
| Tazama Auth | Node | 8083 | PostgreSQL, Redis | — |
| Tazama Rule Exec | Go | 8084 | PostgreSQL, Redis | NATS (both) |
| Dashboard | TypeScript | 3002 | — | REST (client) |
| PostgreSQL | — | 5432 | Disk | — |
| Redis | — | 6379 | RAM | — |
| NATS | Go | 4222, 8222 | Disk | — |
Payment Lifecycle (Step by Step)
Customer initiates payment
A customer clicks 'Pay' on your checkout page. The payment request is sent to Hyperswitch via the merchant dashboard, your backend, or the embedded checkout.
Hyperswitch routes to connector
Hyperswitch evaluates the payment method, currency, and amount. It selects the optimal connector based on your routing rules (cost-based, volume-based, or fallback).
Fraud pre-check (Tazama)
Before sending to the connector, Tazama evaluates the transaction against your fraud rules: amount thresholds, velocity checks, BIN country geo-blocking, and custom rules.
Connector processes payment
Hyperswitch sends the payment to the selected connector. The connector handles 3DS authentication, card tokenization, and bank-side authorization.
Event published to NATS
Hyperswitch publishes a payment event (succeeded, failed, or processing) to the PAYMENT_EVENTS stream. This triggers all downstream consumers.
Webhook delivery
Your application receives a webhook callback with the final payment status. Webhook retries happen up to 3 times with 30-second acknowledgment windows.
Invoice & subscription sync
NATS-KB Bridge syncs the completed payment to Kill Bill for invoice generation, subscription billing, and dunning if needed.
Provider-Agnostic Architecture
One of OpenPay's core design principles is that you should never be locked into a single payment processor. Hyperswitch acts as a universal adapter between your application and 100+ payment processors worldwide.
Switch Processors Without Code Changes
Update routing rules in the Hyperswitch dashboard and payments are instantly rerouted to the new processor. No redeployment, no code changes, no downtime.
Fallback & Smart Routing
Configure primary and fallback processors. If the primary fails, Hyperswitch automatically retries with the fallback. Route by currency, amount, or payment method.
Deep Dives
External Architecture Resources
Hyperswitch Architecture
Understand how Hyperswitch routes payments, handles retries, and manages connectors
NATS JetStream Design
Streams, consumers, delivery guarantees, and exactly-once semantics
Kill Bill Architecture
Subscription lifecycle, invoice generation, and plugin system
Docker Networking Guide
Bridge networks, overlay networks, and service discovery in Docker Compose