Orders Service — Deployment Topology
Status: populated Owner: TBD Last updated: 2026-04-18 Companion: Service Template · SERVICE_OVERVIEW · 17 Technology Stack
1. Runtime
| Attribute | Value |
|---|---|
| Runtime | Node.js 22 LTS / NestJS 11 |
| Language | TypeScript 5.x |
| Container image | ghcr.io/ghasitech/orders-service:latest |
| Port | 3010 (HTTP) |
| Protocol | HTTP/1.1 (internal), HTTP/2 optional via Kong |
| Health endpoints | GET /health/live, GET /health/ready, GET /health/startup |
2. Kubernetes Deployment
3. Replica and Scaling Policy
| Environment | Min replicas | Max replicas | Scale trigger |
|---|---|---|---|
| Production | 3 | 8 | CPU ≥ 65% or p95 latency > 700 ms |
| Staging | 2 | 4 | CPU ≥ 70% |
| Development | 1 | 1 | n/a |
Anti-affinity: Pod anti-affinity rules ensure replicas do not share a node (zone-spread preferred).
PodDisruptionBudget: minAvailable: 2 — at least 2 replicas available during rolling updates.
4. Regions and Data Residency
| Deployment target | Region | Notes |
|---|---|---|
| Primary prod | Afghanistan (AFG) — on-premise or private cloud | MoPH data residency requirement |
| DR / Secondary | Configurable per tenant | Same-region preferred; cross-region requires MoPH approval |
| Staging | Same infrastructure as prod (separate namespace) | Data anonymised |
Data residency is enforced at the PostgreSQL and NATS storage level. No patient data leaves the declared jurisdiction without explicit tenant consent configuration.
5. Resource Requests and Limits
| Container | CPU request | CPU limit | Memory request | Memory limit |
|---|---|---|---|---|
orders-service | 200m | 1000m | 256Mi | 512Mi |
| Init container (migrate) | 100m | 200m | 128Mi | 256Mi |
6. Dependencies at Runtime
| Dependency | Type | Required | Fallback |
|---|---|---|---|
PostgreSQL 16 (orders schema) | Data store | Yes — hard | Circuit-breaker; 503 on startup |
| NATS JetStream | Event bus | Yes — for outbox relay | Outbox buffered in DB; relay retries |
| Redis | Allergy cache + idempotency keys | Yes | Fallback to DB cache (degraded, slower) |
| terminology-service | CDS rule lookup | Yes — soft | CDS check skipped with CDS_DEGRADED alert (hard-stop rules disabled) |
| medication-service | Drug interaction reference | Yes — soft | CDS degraded |
| registration-service | Patient/encounter validation | Yes — hard | 503 returned if unreachable |
| Keycloak | JWT validation | Yes — hard | 401 until recovered |
7. Database Schema Isolation
The orders-service operates on the orders schema in the shared PostgreSQL cluster. Row-Level Security (RLS) is enforced on all tables with tenant_id as partition key. The service connects using a dedicated orders_service_role DB role with no cross-schema read access.
8. Outbox Relay Worker
The outbox relay is a co-located worker thread within the same NestJS process. It polls orders.outbox every 500 ms, publishes pending events to NATS JetStream, and marks them delivered. A distributed lock (Redis SETNX) prevents duplicate relay across pods.
9. Rolling Update Strategy
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
Pre-stop hooks drain in-flight requests with a 15-second grace period. Database migrations run as a separate Job before the Deployment rollout begins.
10. Canary Deploy
Production changes use a 5% canary weight via Kong's weighted routing for 30 minutes before full rollout. Rollback is triggered automatically if error rate > 1% during canary window.
11. Environment Variables (Key)
| Variable | Purpose |
|---|---|
DATABASE_URL | PostgreSQL connection string (Vault-injected) |
NATS_URL | NATS JetStream URL |
REDIS_URL | Redis for cache and locks |
CDS_SERVICE_URL | CDS engine HTTP endpoint |
TERMINOLOGY_SERVICE_URL | terminology-service base URL |
REGISTRATION_SERVICE_URL | registration-service base URL |
KEYCLOAK_REALM_URL | Keycloak realm issuer URL |
ORDERS_TENANT_ISOLATE | Feature flag: RLS enforcement (default true) |
All secrets injected via Vault Agent Injector; never stored in image or ConfigMap.
12. Open Questions
- Dedicated read replica for high-volume patient order list queries — evaluate when p95 > SLO consistently.