Skip to content

C4 Deployment Diagram

Field Value
Status Draft
Owner Platform Engineering / Infrastructure
Last Updated 2026-04-03
Applies To All environments

1. Overview

This document describes the physical deployment topology of the Simpaisa payment gateway. The platform spans Cloudflare's global edge network and AWS regions managed by ControlPlane.com, with data residency requirements driving multi-region SurrealDB placement. Kubernetes namespaces provide environment and product isolation.

2. Deployment Diagram

graph TB
    subgraph "Cloudflare Global Edge"
        CF_DNS["Cloudflare DNS<br/>simpaisa.com, api.simpaisa.com"]
        CF_CDN["Cloudflare CDN<br/>Static asset caching"]
        CF_WAF["Cloudflare WAF<br/>DDoS protection, OWASP rules"]
        CF_Workers["Cloudflare Workers<br/>Edge logic, geo-routing"]
        CF_Pages["Cloudflare Pages<br/>Merchant Portal MFEs"]
    end

    subgraph "AWS — PK Region (ap-south-1)"
        subgraph "ControlPlane.com — K8s Cluster (PK)"
            subgraph "Namespace: payin-prod"
                PayInProd["pay-in-svc<br/>+ channel adapters<br/>+ Caddy sidecar"]
            end
            subgraph "Namespace: payout-prod"
                PayOutProd["pay-out-svc<br/>+ channel adapters<br/>+ Caddy sidecar"]
            end
            subgraph "Namespace: remit-prod"
                RemitProd["remit-svc<br/>+ fx-svc + aml-svc<br/>+ Caddy sidecar"]
            end
            subgraph "Namespace: cards-prod"
                CardsProd["cards-svc<br/>+ token-vault + 3ds-svc"]
            end
            subgraph "Namespace: cards-cde-prod"
                CardsCDE["SurrealDB (CDE)<br/>PCI DSS isolated"]
            end
            subgraph "Namespace: platform-prod"
                PlatformProd["merchant-svc, notification-svc<br/>fraud-svc, recon-svc, settlement-svc<br/>BFF, KrakenD"]
            end
            subgraph "Namespace: temporal-prod"
                TemporalProd["Temporal Server<br/>+ Workers"]
            end
            subgraph "Namespace: messaging-prod"
                NSQProd["nsqd × 3<br/>nsqlookupd × 2"]
            end
            subgraph "Namespace: data-prod"
                SurrealPK["SurrealDB Cluster (PK Primary)<br/>PK, NP, IQ data"]
                RedisProd["Redis Cluster<br/>6 nodes"]
                MeilisearchProd["Meilisearch"]
            end
            subgraph "Namespace: observability-prod"
                OTelProd["OTel Collector<br/>Grafana, Jaeger, Prometheus, Loki"]
            end
        end
    end

    subgraph "AWS — BD Region (ap-southeast-1)"
        subgraph "ControlPlane.com — K8s Cluster (BD)"
            subgraph "Namespace: payin-prod-bd"
                PayInBD["pay-in-svc (BD)<br/>+ BD channel adapters"]
            end
            subgraph "Namespace: payout-prod-bd"
                PayOutBD["pay-out-svc (BD)<br/>+ BD channel adapters"]
            end
            subgraph "Namespace: data-prod-bd"
                SurrealBD["SurrealDB Cluster (BD Secondary)<br/>Bangladesh data residency"]
                RedisBD["Redis Cluster (BD)"]
            end
        end
    end

    CF_DNS --> CF_CDN
    CF_CDN --> CF_WAF
    CF_WAF --> CF_Workers
    CF_Workers -- "PK/NP/IQ traffic" --> PlatformProd
    CF_Workers -- "BD traffic" --> PayInBD
    CF_Pages --> CF_CDN

    PlatformProd --> PayInProd
    PlatformProd --> PayOutProd
    PlatformProd --> RemitProd
    PlatformProd --> CardsProd
    PayOutProd --> TemporalProd
    RemitProd --> TemporalProd
    PayInProd --> NSQProd
    PayOutProd --> NSQProd
    PayInProd --> SurrealPK
    PayOutProd --> SurrealPK
    RemitProd --> SurrealPK
    CardsProd --> CardsCDE

    SurrealPK -. "Async replication<br/>(metadata only)" .-> SurrealBD

3. Namespace Strategy

Each environment × product combination gets its own Kubernetes namespace:

Environment Namespaces
sandbox payin-sandbox, payout-sandbox, remit-sandbox, cards-sandbox, platform-sandbox
dev payin-dev, payout-dev, remit-dev, cards-dev, platform-dev
test payin-test, payout-test, remit-test, cards-test, platform-test
prod payin-prod, payout-prod, remit-prod, cards-prod, cards-cde-prod, platform-prod

Isolation guarantees: - Network policies restrict cross-namespace traffic (e.g. sandbox cannot reach prod). - Resource quotas prevent one namespace from starving another. - RBAC limits developer access: squad members can deploy to their product namespace only.

4. Cloudflare Edge Layer

Component Purpose
DNS Authoritative DNS for all Simpaisa domains
CDN Cache static assets, reduce origin load
WAF OWASP Core Rule Set, custom rules for API abuse
DDoS Protection Automatic L3/L4/L7 mitigation
Workers Geo-routing (PK↔BD), request signing, edge auth
Pages Merchant Portal hosting with preview deployments

Geo-routing logic in Cloudflare Workers:

IF request.country IN [BD] → route to BD cluster
ELSE → route to PK cluster (default)

5. Multi-Region Data Topology

graph LR
    subgraph "PK Region (Primary)"
        SurrealPK2["SurrealDB Cluster<br/>PK, NP, IQ data<br/>3 nodes"]
        RedisPK2["Redis Cluster<br/>6 nodes"]
    end

    subgraph "BD Region (Secondary)"
        SurrealBD2["SurrealDB Cluster<br/>BD data only<br/>3 nodes"]
        RedisBD2["Redis Cluster<br/>6 nodes"]
    end

    SurrealPK2 -. "Cross-region replication<br/>(metadata, config only)" .-> SurrealBD2

Data residency rules: - Bangladesh transaction data must reside in the BD region cluster. - Pakistan, Nepal, and Iraq data resides in the PK region cluster. - Merchant configuration and platform metadata replicate across both regions. - The CDE SurrealDB cluster is PK-region only (single PCI DSS audit scope).

6. Scaling Parameters

Component PK Region BD Region
KrakenD 4 replicas, HPA 4→12 2 replicas, HPA 2→6
pay-in-svc 6 replicas, HPA 6→20 3 replicas, HPA 3→10
pay-out-svc 4 replicas, HPA 4→12 2 replicas, HPA 2→8
remit-svc 3 replicas, HPA 3→8
cards-svc 3 replicas, HPA 3→8
SurrealDB 3 nodes 3 nodes
Redis 6 nodes (3P + 3R) 6 nodes (3P + 3R)
NSQ (nsqd) 3 nodes 2 nodes
Temporal 3 frontend, 3 history

HPA = Horizontal Pod Autoscaler, triggered by CPU (70%) and request rate.

7. Disaster Recovery

Scenario RTO RPO Strategy
Single pod failure < 30 s 0 K8s auto-restart
Single node failure < 2 min 0 K8s rescheduling
PK region degradation < 15 min < 1 min BD region serves BD traffic; PK restored
SurrealDB node failure < 5 min 0 Cluster self-healing
Full region loss (PK) < 60 min < 5 min Manual failover to DR region

8. CI/CD Pipeline

graph LR
    Dev["Developer"] --> BB["Bitbucket<br/>Pull Request"]
    BB --> Pipeline["Bitbucket Pipelines"]
    Pipeline --> Lint["Lint + Test"]
    Lint --> Build["Docker Build"]
    Build --> Push["Push to ECR"]
    Push --> Deploy["ControlPlane.com<br/>K8s Deploy"]
    Deploy --> Sandbox["sandbox"]
    Sandbox --> Test["test"]
    Test --> Prod["prod<br/>(manual gate)"]

Deployments progress through sandbox → test → prod. Production deployments require manual approval from a squad lead or platform engineer.

9. Architectural Decision Records

Changes to deployment topology require an ADR in /Standards/ADR/.