Skip to content

Microservices Framework

Field Value
Status Draft
Owner Platform Engineering
Last Updated 2026-04-03
Applies To All backend services

1. Overview

Simpaisa processes 270M+ transactions annually across Pakistan, Bangladesh, Nepal, Iraq and Egypt. This document defines the microservices architecture that underpins all product lines — Pay-Ins, Pay-Outs, Remittances and Cards — ensuring consistent service design, communication patterns and operational readiness.

2. Service Decomposition

2.1 Product Services

Service Responsibility Owner
pay-in-svc Charge initiation, OTP validation, callback handling Pay-In Squad
pay-out-svc Disbursements, batch payouts, settlement reconciliation Pay-Out Squad
remit-svc Cross-border quotes, AML screening, corridor routing Remit Squad
cards-svc Authorisation, capture, void, refund, 3DS orchestration Cards Squad

2.2 Shared Services

Service Responsibility
merchant-svc Merchant onboarding, API key lifecycle, configuration
notification-svc Webhooks, SMS, email dispatch via NSQ consumers
fx-svc Real-time FX rate fetching, spread calculation, caching
fraud-svc Rule engine, velocity checks, ML scoring
recon-svc End-of-day reconciliation against channel statements
settlement-svc Net settlement calculation, ledger posting

3. Inter-Service Communication

3.1 Synchronous — gRPC

All service-to-service synchronous calls use gRPC with Protocol Buffers v3. Protobuf definitions live in a shared simpaisa-proto repository.

  • Timeouts: 3 s default, 10 s for channel adapter calls.
  • Retries: Automatic with exponential back-off (max 3 attempts).
  • Load balancing: Client-side round-robin via K8s headless services.

3.2 Asynchronous — NSQ

Event-driven workflows use NSQ topics. Each service publishes domain events; downstream services subscribe via dedicated channels.

Topic Publisher Subscribers
txn.payin.completed pay-in-svc notification-svc, recon-svc
txn.payout.initiated pay-out-svc fraud-svc, settlement-svc
txn.remit.aml.cleared remit-svc pay-out-svc
txn.cards.authorised cards-svc notification-svc, fraud-svc

4. Service Discovery

Service discovery uses Kubernetes DNS. Each service is addressable as <service>.<namespace>.svc.cluster.local. No external service registry is required.

Environment-specific routing:

pay-in-svc.payin-prod.svc.cluster.local
pay-out-svc.payout-prod.svc.cluster.local

5. Health Checks

Every service must expose two HTTP endpoints on a dedicated health port (default :9090):

Endpoint Purpose K8s Probe
/health Liveness — process is running livenessProbe
/ready Readiness — dependencies are healthy readinessProbe

The /ready check must verify connectivity to SurrealDB, Redis, and NSQ before returning 200 OK.

6. Resilience Patterns

6.1 Circuit Breakers

All outbound calls to external channel partners use circuit breakers implemented via the sony/gobreaker library.

Parameter Default
Failure threshold 5
Success threshold 3
Timeout (half-open) 30 s

6.2 Bulkhead Isolation

Each channel adapter runs in its own goroutine pool with a bounded semaphore. A misbehaving channel (e.g. Easypaisa timeout spike) cannot exhaust resources for other channels (e.g. JazzCash, bKash).

// Per-adapter concurrency limit
sem := make(chan struct{}, cfg.MaxConcurrent) // e.g. 200

6.3 Graceful Degradation

  • If fraud-svc is unavailable, pay-in transactions below the risk threshold (PKR 5,000) proceed with a flag for deferred screening.
  • If fx-svc is unavailable, remit-svc returns the last cached rate with a staleness indicator.
  • If notification-svc is down, events remain on the NSQ topic and are processed on recovery.

7. Security — mTLS via Caddy Sidecar

Every pod runs a Caddy sidecar that terminates and originates mTLS. Certificates are issued by ControlPlane.com's built-in CA and rotated automatically every 24 hours.

# K8s pod spec excerpt
containers:
  - name: caddy
    image: caddy:2-alpine
    ports:
      - containerPort: 443
    volumeMounts:
      - name: certs
        mountPath: /etc/caddy/certs

8. Configuration

All runtime configuration is injected via environment variables, sourced from Kubernetes ConfigMaps and Secrets. No configuration files are baked into container images.

Variable Example
SURREAL_DSN ws://surrealdb:8000/rpc
NSQ_LOOKUPD_ADDR nsqlookupd:4161
OTEL_EXPORTER_ENDPOINT otel-collector:4317
POSTHOG_API_KEY phc_xxxxx

9. Feature Flags

Feature flags are managed via PostHog Feature Flags. Services evaluate flags at runtime using the PostHog Go SDK.

Use cases: - Rolling out a new channel adapter (e.g. enable_alfa_wallet_pk). - Toggling async vs sync charge flow per merchant. - A/B testing fraud rule thresholds.

10. Service Template

All new services are scaffolded from the simpaisa-go-template repository, which provides:

  • Standard project layout (/cmd, /internal, /pkg, /api).
  • gRPC server and client boilerplate.
  • NSQ publisher/subscriber wiring.
  • Health check endpoints.
  • OpenTelemetry tracing and metrics instrumentation.
  • Dockerfile with multi-stage build.
  • Helm chart with Caddy sidecar.
  • CI pipeline definition for Bitbucket Pipelines.
# Scaffold a new service
cookiecutter [email protected]:simpaisa/simpaisa-go-template.git \
  --no-input service_name=new-svc

11. Architectural Decision Records

Changes to this framework require an ADR in /Standards/ADR/. See ADR/ADR-TEMPLATE.md.