Webhook Dispatcher — Deployment Topology
Status: populated Owner: Platform Engineering Last updated: 2026-04-18 Companion: LOCAL_DEV_SETUP · OBSERVABILITY
1. Kubernetes Workload
apiVersion: apps/v1
kind: Deployment
metadata:
name: webhook-dispatcher
namespace: sms-gateway
spec:
replicas: 3
selector:
matchLabels:
app: webhook-dispatcher
template:
spec:
containers:
- name: webhook-dispatcher
image: ghasi/webhook-dispatcher:latest
ports:
- containerPort: 3000
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "512Mi"
livenessProbe:
httpGet: { path: /health, port: 3000 }
initialDelaySeconds: 10
periodSeconds: 15
readinessProbe:
httpGet: { path: /ready, port: 3000 }
initialDelaySeconds: 5
periodSeconds: 10
envFrom:
- secretRef: { name: webhook-dispatcher-secrets }
- configMapRef: { name: webhook-dispatcher-config }
2. Kong Gateway Routes
# Kong route for REST API
services:
- name: webhook-dispatcher
url: http://webhook-dispatcher.sms-gateway.svc.cluster.local:3000
routes:
- name: webhooks-api
paths: ["/v1/webhooks"]
methods: ["GET", "POST", "PUT", "DELETE"]
plugins:
- name: jwt # Validates customer JWT; injects X-Account-Id
- name: rate-limiting
config:
minute: 60 # 60 REST requests/min per account
- name: request-size-limiting
config:
allowed_payload_size: 1 # 1 KB max request body
3. Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: webhook-dispatcher-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: webhook-dispatcher
minReplicas: 3
maxReplicas: 15
metrics:
- type: External
external:
metric:
name: nats_consumer_pending_messages
selector:
matchLabels:
consumer: webhook-dispatcher
target:
type: AverageValue
averageValue: "200"
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
4. Network Topology
Internet (customer endpoints) ◄── webhook-dispatcher pods ◄── NATS webhook.dispatch
Kong (REST API, internal) ──► webhook-dispatcher pods ──► PostgreSQL hook schema
──► NATS webhook.dispatch.deadletter
Egress to customer URLs: pods have unrestricted HTTPS egress (port 443) via NAT gateway. All other egress restricted by NetworkPolicy.
5. Environment Variables
| Variable | Description | Example |
|---|---|---|
NATS_URL | NATS server URL(s) | nats://nats:4222 |
DATABASE_URL | PostgreSQL connection string | postgresql://hook_svc:***@pg:5432/ghasi |
DB_POOL_MIN | Min pool size | 5 |
DB_POOL_MAX | Max pool size | 20 |
KMS_KEY_ID | KMS key for webhook secret encryption | arn:aws:kms:eu-west-1:... |
HTTP_DELIVERY_TIMEOUT_MS | HTTP delivery timeout | 5000 |
RETRY_WORKER_INTERVAL_MS | Retry poller interval | 10000 |
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP collector | http://otel-collector:4318 |
LOG_LEVEL | Pino log level | info |
PORT | HTTP port | 3000 |
6. Secrets Management
| Secret | Storage | Rotation |
|---|---|---|
DATABASE_URL | Vault KV v2 → K8s Secret | 90 days |
KMS_KEY_ID + access credentials | Vault KV v2 / IAM role | Managed by cloud provider |
| NATS TLS cert + key | Vault PKI | 30 days |