a month ago
Our production service is experiencing a reproducible outbound networking issue when connecting to a Supabase Session Pooler.
The application itself deploys successfully and its HTTP health check passes.
We reproduced the issue in two Railway regions: Amsterdam and Singapore.
Amsterdam runtime:
- DNS resolution for example.com: PASS
- DNS resolution for supabase.com: PASS
- DNS resolution for the valid Supabase Session Pooler hostname: FAIL with EAI_NONAME
- Railway DNS/network logs show no corresponding DNS query
- Using an externally resolved IPv4 for the same Pooler endpoint, outbound TCP/5432 times out
Singapore runtime:
- Generic external DNS resolution: PASS
- The same Supabase Session Pooler hostname fails with EAI_NONAME
- Railway DNS/network logs again show no corresponding DNS query
The Pooler hostname and connection configuration have been validated.
The service deployment itself succeeds and the HTTP health endpoint remains healthy.
No database migrations or writes were attempted during these diagnostics.
Could Railway please help determine:
- Why can the runtime resolve normal public domains but not this valid Supabase Session Pooler hostname?
- Why are the failed Pooler DNS lookups absent from Railway DNS/network logs?
- Why does direct outbound TCP/5432 to an externally resolved Pooler IPv4 also time out?
- Are there any resolver, routing, firewall, or outbound TCP/5432 restrictions affecting Supabase Session Pooler endpoints?
I can provide the relevant Project, Service, Environment, and Deployment IDs privately to Railway staff if needed.
2 Replies
a month ago
This thread has been opened as a bounty so the community can help solve it.
Status changed to Open Railway • about 1 month ago
a month ago
There are two important corrections to the previous diagnosis.
Supabase's Shared Pooler (Supavisor) is IPv4-only, not IPv6-only. Session mode is aws-[region].pooler.supabase.com:5432; transaction mode uses the same IPv4 pooler infrastructure on port 6543. Therefore forcing ipv4first or enabling IPv6 should not be required to resolve a valid Session Pooler hostname.
Also, a raw TCP connection timing out to IPv4:5432 cannot be caused by missing PostgreSQL project reference, credentials, or TLS SNI. Those are evaluated after the TCP connection has been established.
I would split this into DNS and TCP diagnostics.
First, inside the affected Railway runtime, inspect the hostname exactly:
node -e 'const h=process.env.DB_HOST; console.log(JSON.stringify(h), h?.length)'
This catches trailing whitespace/newlines or other characters that can cause getaddrinfo() to return EAI_NONAME locally.
Then compare the resolver paths:
getent ahostsv4 "$DB_HOST"
node -e 'require("dns").lookup(process.env.DB_HOST,{all:true},console.log)'
node -e 'require("dns").resolve4(process.env.DB_HOST,console.log)'
If resolve4() succeeds while lookup() fails, that strongly points to the libc/NSS resolver path rather than Supabase DNS itself.
Railway documents that its DNS logs record every service DNS lookup. So if these tests genuinely issue a lookup for the exact pooler hostname and no corresponding Railway DNS event exists, that is useful evidence for Railway to inspect the resolver/logging path rather than assuming the domain is IPv6-only.
For the TCP side, test the IPv4 returned by resolve4() and inspect Railway's egress network logs for port 5432. In particular, look for whether the flow is recorded as ok or dropped and any drop_cause.
Also check Supabase Database → Network Restrictions. Supabase network restrictions apply to both direct Postgres and the pooler. If Railway's current egress IPs are not allowed, the connection can be silently blocked before PostgreSQL authentication.
I would not switch from Session Pooler 5432 to Transaction Pooler 6543 merely as a DNS workaround; that changes pooling semantics and does not explain why a valid pooler hostname cannot resolve.
So the useful decision tree is:
malformed runtime hostname → fix configuration;
lookup() fails but resolve4() succeeds → libc/NSS resolver issue;
DNS resolves but TCP/5432 is dropped → inspect Railway network flow + Supabase Network Restrictions;
clean hostname + failed DNS with no Railway DNS event → Railway-side resolver/observability investigation.
This should distinguish the actual failure without changing database pooling mode or assuming an IPv6 requirement that Supavisor does not have.
a month ago
sound like they didn’t own ythe tech!