fix(GRO-2652): boot ECONNRESET resilience — retry-with-backoff in initAuth, server-first startup #222
Reference in New Issue
Block a user
Delete Branch "feature/GRO-2652-boot-econnreset-resilience"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
PROD
groombook/apipod (rev-50,2026.06.26-98b1171) entered CrashLoopBackOff after a transient PostgresECONNRESETat boot. The process exited immediately with no HTTP traffic served.Root cause (two compounding issues):
src/index.ts:await initAuth()was a bare top-level ESMawait. Any rejection propagated as an uncaught module-evaluation error →process.exit(1)before the server even bound to port 3000./healthwas never reachable during the crash window, so K8s liveness/readiness probes failed immediately.src/lib/auth.ts: The DB query insideinitAuth()had no error handling. A singleECONNRESETfrom theauth_provider_configquery causedauthInitPromiseto reject, propagating out to the top-level await above.The
src/lib/auth.tsfile is byte-for-byte identical between rev-49 and rev-50 — the timing correlation with rev-50's deploy is incidental. Rollback to rev-49 would not fix the root bug; forward fix is mandatory (AC#2).Changes
src/lib/auth.tsauth_provider_configDB query in retry-with-backoff: up to 5 attempts, exponential 1 s / 2 s / 4 s / 8 s delayECONNRESETno longer rejectsauthInitPromisesrc/index.tsserve()+console.logmoved beforeinitAuth()— HTTP server binds immediately so/healthand all public routes are available from pod startinitAuth()now runs in a retry loop: up to 10 attempts, exponential 500 ms → 30 s503via the existingcatch-to-503inauthRouterstartReminderScheduler()also moved before the auth retry loop so background jobs are not blockedUAT_PLAYBOOK.mdDB Migration Compatibility
GRO-2586 (rev-50) made zero schema changes. Rollback to rev-49 is schema-safe. These changes also make no schema changes — no migrations.
Test Coverage
UAT_PLAYBOOK.mdSDLC
Phase 1 of 4 — feature → dev. CI must pass before merge.
cc @cpfarhood