Repository navigation
fix: migrate prod db off neon free-tier to railway postgres + resilience hardening - #104
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
All CLI users saw
Distro TV — offline demo (backend not reachable)instead of channel content. Root cause: the prod Postgres (Neon free-tier) exhausted its account compute-time quota (HTTP 402) → compute force-suspended (Jun 19) + branch archived (Jun 20) → API DB connections timed out →/me/content/next500'd → CLI fell back to the demo fixture. Contributing factors: the uncached/healthSELECT 1kept the Neon compute pinned active 24/7 (burning the quota), and no alerting meant the outage was silent for ~4 days.What
Prod Postgres moved to Railway Postgres (co-located in the API's Railway project, private networking) — already restored out-of-band (Phase 0). This PR is the supporting code + docs (Phase 1):
railwayDB target —env.dbTargetacceptslocal | neon | railway; the dev-safety guardassertEnvSafenow refuses any non-local target in dev (was neon-only).neon/localkeep working.dbUrlForTarget+ pool options — extracted, testable URL resolver; explicitpostgres()options (max: 10, connect_timeout: 10, idle_timeout: 30) so idle connections close.probeDb— 10s success cache mirroringprobeRedis, killing the per-pollSELECT 1storm (only success is cached; failures re-probe and surface fast).Spec + plan:
docs/superpowers/specs|plans/2026-06-23-prod-db-railway-migration-*.mdValidation
migrate.jswithDB_TARGET=railwayrun against the real Railway Postgres →[migrate] up to date (target=remote).DB_TARGET=railway→/health200 ok, and/me/content/nextserved real news + markets (no demo fixture)./me/content/next) returns 5 news + 5 ticker, real headlines + live quotes.After merge (manual, gated on this deploying first)
Flip Railway
DB_TARGET=railway, then verify/healthisokand deploy logs show[migrate] up to date (target=remote).neonstill resolves identically, so the deploy is safe before the flip.Follow-ups (non-blocking)
/healthdegraded alerting (the actual "never silent again" fix).drizzle.config.tsremote fallback toDATABASE_URL_UNPOOLED ?? DATABASE_URL(pre-existing, off the prod path).