Skip to main content

The Discovery

When running railway variables from an app service context, the DATABASE_URL returned uses Railway’s internal hostname (postgres.railway.internal) which is unreachable from outside Railway’s network. This caused repeated seeding failures where scripts appeared to connect but timed out or errored. The fix: Railway’s database service exposes a separate DATABASE_PUBLIC_URL variable with a public TCP proxy (caboose.proxy.rlwy.net:{port}). This URL is only visible when querying the database service’s variables directly:
railway variables --json -s traceo:database | python3 -c \
  "import sys,json; print(json.load(sys.stdin)['DATABASE_PUBLIC_URL'])"

Why This Matters

Three previous seeding attempts failed because they all assumed railway run or railway variables on the app service would provide a usable connection string. The correct pattern is: always query the database service for connection details when connecting from outside Railway. This applies to local development, CI/CD pipelines, and one-off administrative scripts.

Operational Impact

With the public proxy URL discovered, the full choco-hq + stratt-specs seed pipeline ran in under 5 seconds, inserting 113 requirements directly from a local machine. A reproducible runbook (scripts/seed_railway.sh) now wraps this for future use.