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/.