Redis connection failing with ECONNREFUSED - Reference variables not resolving
kerebere
PROOP

23 days ago

I'm experiencing a persistent Redis connection issue in my NestJS application. The app starts successfully but immediately fails to connect to Redis with ECONNREFUSED errors, causing healthcheck failures.

Environment Details:

Project: lumen

Environment: Development

Region: EU West (europe-west4-drams3a)

Development Service ID: c94d8ea5-f995-4c07-9465-365371abde40

Redis Service ID: b35df8da-a1af-4e49-86db-313f9588b2b8

Latest Deployment ID: a4987cb5-241b-4d99-a2bb-c36afbab941c

Current Configuration:

REDIS_URL=redis://default:${{Redis.REDIS_PASSWORD}}@${{Redis.RAILWAY_PRIVATE_DOMAIN}}:6379

Problem:

NestJS app starts successfully and binds to port 8080

Immediately after startup, ioredis throws continuous AggregateError [ECONNREFUSED] errors

Redis service is healthy and running (1/1 replicas, no failures)

Error is ECONNREFUSED (TCP connection refused), not ENOTFOUND (DNS failure)

Healthcheck fails with: MaxRetriesPerRequestError: Reached the max retries per request limit (which is 20)

Critical observation: Logs show "[RedisService] Redis connected" immediately followed by ECONNREFUSED errors, suggesting a race condition

Attempted Fixes (all failed):

Corrected service name from redis-dev to Redis

Tried using ${{ Redis.REDIS_URL }}

Tried using ${{ Redis.REDIS_PUBLIC_URL }}

Tried hardcoded private domain with reference variables for password

Disabled healthcheck - connection still fails

Multiple redeployments

Solved$20 Bounty

Pinned Solution

ve-jo
HOBBYTop 5% Contributor

22 days ago

The clue could be here in this line:

[RedisService] Redis connected immediately followed by ECONNREFUSED

That means one Redis client is connecting successfully, but another Redis in the app is still using a different config, often the default localhost:6379.

I would check the actual host/port in the ECONNREFUSED stack trace. Network Flow Logs in your deployment could be useful there.

If it says 127.0.0.1:6379 or ::1:6379, the failing client is not using your Railway Redis URL.

Then, because this is ioredis on Railway private networking, add dual-stack lookup support:

const redis = new Redis(${process.env.REDIS_URL}?family=0);

So, for your debugging I’d use is:

  1. Print the resolved REDIS_URL at startup (maybe also mask the password just in case).
  2. Check whether the ECONNREFUSED target is localhost, ::1, or the Railway private internal host.
  3. Make sure every Redis-using module gets the same parsed config.

Hope you find something.

8 Replies

Status changed to Open Railway 23 days ago


I'd try redeploying your Redis instance.


ve-jo
HOBBYTop 5% Contributor

22 days ago

The clue could be here in this line:

[RedisService] Redis connected immediately followed by ECONNREFUSED

That means one Redis client is connecting successfully, but another Redis in the app is still using a different config, often the default localhost:6379.

I would check the actual host/port in the ECONNREFUSED stack trace. Network Flow Logs in your deployment could be useful there.

If it says 127.0.0.1:6379 or ::1:6379, the failing client is not using your Railway Redis URL.

Then, because this is ioredis on Railway private networking, add dual-stack lookup support:

const redis = new Redis(${process.env.REDIS_URL}?family=0);

So, for your debugging I’d use is:

  1. Print the resolved REDIS_URL at startup (maybe also mask the password just in case).
  2. Check whether the ECONNREFUSED target is localhost, ::1, or the Railway private internal host.
  3. Make sure every Redis-using module gets the same parsed config.

Hope you find something.


ve-jo
HOBBYTop 5% Contributor

22 days ago

Also, I would recommend you to from manually building this line in other services in their environments:

REDIS_URL=redis://default:${{Redis.REDIS_PASSWORD}}@${{Redis.RAILWAY_PRIVATE_DOMAIN}}:6379

to use just this:

REDIS_URL=${{ Redis.REDIS_URL }}

because its just the same (and private networking still) and you wont do typo or something.


ve-jo

Also, I would recommend you to from manually building this line in other services in their environments: `REDIS_URL=redis://default:${{Redis.REDIS_PASSWORD}}@${{Redis.RAILWAY_PRIVATE_DOMAIN}}:6379` to use just this: `REDIS_URL=${{ Redis.REDIS_URL }}` because its just the same (and private networking still) and you wont do typo or something.

kerebere
PROOP

22 days ago

Tried both, didnt help


ve-jo

The clue could be here in this line: > `[RedisService] Redis connected` immediately followed by ECONNREFUSED That means one Redis client is connecting successfully, but another Redis in the app is still using a different config, often the default `localhost:6379`. I would check the actual host/port in the ECONNREFUSED stack trace. Network Flow Logs in your deployment could be useful there. If it says `127.0.0.1:6379` or `::1:6379`, the failing client is not using your Railway Redis URL. Then, because this is ioredis on Railway private networking, add dual-stack lookup support: const redis = new Redis(`${process.env.REDIS_URL}?family=0`); So, for your debugging I’d use is: 1. Print the resolved REDIS_URL at startup (maybe also mask the password just in case). 2. Check whether the ECONNREFUSED target is localhost, ::1, or the Railway private internal host. 3. Make sure every Redis-using module gets the same parsed config. Hope you find something.

kerebere
PROOP

22 days ago

Ill check this one


0x5b62656e5d

I'd try redeploying your Redis instance.

kerebere
PROOP

22 days ago

Nah. Tried as well


kerebere

Nah. Tried as well

ve-jo
HOBBYTop 5% Contributor

22 days ago

Share some logs if still doesn't work. What host/port Redis client actually tries to connect to.


ve-jo

The clue could be here in this line: > `[RedisService] Redis connected` immediately followed by ECONNREFUSED That means one Redis client is connecting successfully, but another Redis in the app is still using a different config, often the default `localhost:6379`. I would check the actual host/port in the ECONNREFUSED stack trace. Network Flow Logs in your deployment could be useful there. If it says `127.0.0.1:6379` or `::1:6379`, the failing client is not using your Railway Redis URL. Then, because this is ioredis on Railway private networking, add dual-stack lookup support: const redis = new Redis(`${process.env.REDIS_URL}?family=0`); So, for your debugging I’d use is: 1. Print the resolved REDIS_URL at startup (maybe also mask the password just in case). 2. Check whether the ECONNREFUSED target is localhost, ::1, or the Railway private internal host. 3. Make sure every Redis-using module gets the same parsed config. Hope you find something.

kerebere
PROOP

22 days ago

Thanks, this one helped me


Status changed to Solved brody 22 days ago


Welcome!

Sign in to your Railway account to join the conversation.

Loading...