Health Check
PayWarden exposes three health endpoints with different audiences and guarantees.
| Endpoint | Auth | Purpose |
|---|---|---|
GET /api/v1/health/live | Public | Liveness probe — process is up |
GET /api/v1/health | Public | Readiness probe — minimal ok / degraded |
GET /api/v1/admin/health | Admin | Detailed dependency + chain status |
GET /api/v1/health/live
Liveness probe. Returns 200 as long as the HTTP server can answer. Does not check the database, Redis, TronGrid, wallet, or chain watcher — this is intentional so a first-deploy bootstrap (pending migrations, uninitialized wallet) does not flap the container into a restart loop.
GET /api/v1/health/liveResponse 200:
{ "status": "alive" }This is the endpoint targeted by docker-compose.yml's HEALTHCHECK.
GET /api/v1/health
Public readiness probe. Exercises DB, Redis, TronGrid, wallet, and chain watcher on every call, but the response body is intentionally minimal — no infrastructure details (DB host, Redis host, block height, sweep config) are exposed on the public surface. Use this behind a load balancer to fail over a degraded instance.
GET /api/v1/healthResponse 200 — healthy:
{ "status": "ok" }Response 503 — degraded:
{ "status": "degraded" }For the breakdown of which dependency is failing, an operator must hit the admin endpoint below.
GET /api/v1/admin/health
Detailed health report. Requires admin authentication (see Authentication). Used by the dashboard and on-call operators to diagnose a degraded instance after the public probe flips to 503.
GET /api/v1/admin/health
Cookie: admin_token=<jwt>Response 200 — healthy:
{
"status": "ok",
"version": "0.1.0",
"uptime": 3600,
"checks": {
"database": "connected",
"redis": "connected",
"trongrid": "reachable",
"watcher": "running",
"wallet": "initialized"
},
"system": {
"tronNetwork": "mainnet",
"currentBlock": 65432100,
"scanMode": "address",
"minConfirmations": 19,
"sweepEnabled": true
}
}Response 503 — degraded: same shape with status: "degraded" and one or more entries under checks showing disconnected / stopped / uninitialized / degraded.
Fields
| Field | Type | Description |
|---|---|---|
status | "ok" | "degraded" | Overall health |
version | string | PayWarden version from package.json |
uptime | number | Process uptime in seconds |
checks.database | "connected" | "disconnected" | PostgreSQL connectivity |
checks.redis | "connected" | "disconnected" | "degraded" | Redis connectivity |
checks.trongrid | "reachable" | "disconnected" | "degraded" | TronGrid reachability |
checks.watcher | "running" | "stopped" | Chain watcher BullMQ job state |
checks.wallet | "initialized" | "uninitialized" | Wallet service init state |
system.tronNetwork | "mainnet" | "nile" | "shasta" | Configured TRON network |
system.currentBlock | number | null | Latest block number reported by TronGrid |
system.scanMode | "address" | "block" | SCAN_MODE env value |
system.minConfirmations | number | MIN_CONFIRMATIONS env value |
system.sweepEnabled | boolean | True when both HOT_WALLET_KEY and COLD_WALLET_ADDRESS are set |
Usage
Docker Compose health check
PayWarden's docker-compose.yml points its HEALTHCHECK at the liveness endpoint so bootstrap conditions do not cause restart loops:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/api/v1/health/live"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10sUptime monitoring
Use the public readiness endpoint with an external uptime monitor — UptimeRobot, Better Uptime, Grafana + blackbox exporter, etc.
curl -sf http://localhost:3000/api/v1/health | jq '.status'Kubernetes liveness / readiness
Map each probe to the matching endpoint — do not point the liveness probe at /api/v1/health, or a transient TronGrid blip will kill the pod.
livenessProbe:
httpGet:
path: /api/v1/health/live
port: 3000
initialDelaySeconds: 5
periodSeconds: 30
readinessProbe:
httpGet:
path: /api/v1/health
port: 3000
initialDelaySeconds: 10
periodSeconds: 10