stack: realtime service cannot run (or be consumed) in docker mode
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 43/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- docker, node.js, postgresql, typescript
- Domain
- api, backend, devops, testing-qa
Research direction
Start with packages/stack/src/services/realtime.ts to trace Docker startup and the missing database connectivity setting. Then inspect ApiProxy.ts, node.ts, and the docker-mode end-to-end suite for websocket upgrade, routing, and coverage behavior. Done means realtime starts reliably, supabase-js can connect through stack.url, and the docker-mode tests cover the path.
Written by the indexing model from the issue text.
Description
Pinned at: develop @ 31d6fb97 · macOS arm64 (Darwin 25.5), Docker Desktop (server 29.5.3), Node 24.18.0, realtime image v2.112.3 (DEFAULT_VERSIONS), consuming @supabase/stack via createStack().
Enabling realtime in docker mode (createStack({ mode: "docker", realtime: { port } })) never reaches ready, and even a healthy realtime container can't be consumed by supabase-js through the stack. Three findings, plus one observation:
1. The realtime container can't reach postgres — start() hangs indefinitely.
The realtime ServiceDef's env (packages/stack/src/services/realtime.ts) doesn't set DB_IP_VERSION. On Docker Desktop for Mac, every connection attempt fails with:
Postgrex.Protocol failed to connect: ** (DBConnection.ConnectionError)
tcp connect (host.docker.internal:53976): network is unreachable - :enetunreach
— while getent ahosts host.docker.internal inside the same image resolves IPv4-only (192.168.65.254), and GoTrue/PostgREST connect fine over the identical wiring. The migration runner gives up after ~15s, the container exits, unless-stopped restart-loops it forever, and stack.start() waits with no diagnostic (the no-timeout behavior noted in supabase/cli#5787 makes this a silent hang).
Verified fix: re-running the identical container with only DB_IP_VERSION=ipv4 added makes migrations run instantly. This looks like the known realtime self-host IPv6-preference gotcha; the ServiceDef probably wants DB_IP_VERSION=ipv4 for the host.docker.internal path.
Worth noting the docker-mode e2e suite doesn't enable realtime, so this path appears never to have been exercised.
2. The ApiProxy can't carry realtime websockets.
The proxy routes /realtime/v1/* as plain HTTP (ApiProxy.ts) and neither it nor the Node platform layer (node.ts — bare createServer()) registers any upgrade handling, so supabase-js — which derives wss://…/realtime/v1/websocket from the project URL — can never connect through stack.url.
3. The direct service endpoint can't serve supabase-js either.
Bypassing the proxy fails independently three ways: the bare realtime server 404s /realtime/v1/websocket (it serves /socket/websocket; the /realtime/v1 prefix is proxy vocabulary), tenant resolution is Host-based (bare-IP → 401 {"message":"Tenant not found in database"}; Host: realtime-dev → 200), and the apikey must be a real JWT since the proxy's publishable-key→JWT transform is HTTP-only. A raw handshake at /socket/websocket with a tenant-bearing hostname and a signed anon JWT does return 101 — so websocket upgrade support in the proxy (path rewrite + tenant Host + the existing auth transform) would make supabase-js work end-to-end with no client changes.
4. Observation, not root-caused: with finding 1 worked around and a 101 handshake established, channel joins still fail with UnableToConnectToTenantDatabase / UnableToConnectToProject — the SEED_SELF_HOST tenant's own (encrypted-settings) connection pool appears not to honor the env-level IPv4 fix. Happy to provide the full repro.
Suggested resolutions: DB_IP_VERSION=ipv4 (or equivalent) in the realtime ServiceDef; websocket upgrade support in the ApiProxy; realtime coverage in the docker-mode e2e.
- Dominant language
- TypeScript
- Stars
- 2.4k
- Forks
- 523
- Avg merge
- 21h 33m
- Merged PRs (30d)
- 258
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from supabase/cli
-
🐛 Bug supabase/cli
-
🐛 Bug supabase/cli
-
Local Kong keeps idle upstream connections longer than PostgREST, causing sporadic 502 on POST/PATCH Open🐛 Bug supabase/cli
-
✨ Feature supabase/cli
-
🐛 Bug supabase/cli
Similar issues
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P3
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 76/100
-
code-quality refactoring
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
github/gh-aw-firewall#8816 ·
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
vercel/react-tweet#225 ·