Population Health Service — Deployment Topology
Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · 03 platform-services
1. Runtime
| Property | Value |
|---|---|
| Runtime | Node.js 22 / NestJS 11 |
| Language | TypeScript 5.x |
| Package | @ghasi/service-population-health |
| Container image | ghasi/population-health-service:<tag> |
| Exposed port | 3030 |
| Health check | GET /health (liveness + readiness) |
2. Replicas and Scaling
| Environment | API replicas | Worker replicas | Scaling trigger |
|---|---|---|---|
| Development | 1 | 1 | — |
| Staging | 2 | 2 | — |
| Production | 3–6 | 2–4 | CPU > 70% OR queue depth > 100 |
Worker processes handle cohort refresh, risk scoring, quality metric computation, HMIS export, and de-identification jobs via NATS JetStream pull consumers.
3. Dependencies
4. Data Residency and Regions
| Environment | Region | Notes |
|---|---|---|
| Production (Afghanistan) | af-central-1 (MoPH sovereign cloud) | PostgreSQL + object storage must remain in-country |
| Staging | af-staging | Same region, isolated namespace |
| DR | af-central-2 (if available) | Async replication; RTO 4h, RPO 1h |
5. Kubernetes Configuration Sketch
apiVersion: apps/v1
kind: Deployment
metadata:
name: population-health-service
spec:
replicas: 3
template:
spec:
containers:
- name: api
image: ghasi/population-health-service:latest
ports:
- containerPort: 3030
resources:
requests: { cpu: "250m", memory: "512Mi" }
limits: { cpu: "1000m", memory: "1.5Gi" }
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef: { name: pophealth-db-secret, key: url }
- name: NATS_URL
value: nats://nats-cluster:4222
- name: DHIS2_BASE_URL
valueFrom:
configMapKeyRef: { name: pophealth-config, key: dhis2_url }
6. NATS Stream Bootstrap
nats stream add POPULATION_HEALTH \
--subjects "population_health.>" \
--storage file \
--replicas 3 \
--retention limits \
--max-age 14d \
--max-msg-size 131072