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

2 months 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
HOBBY

2 months 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 about 2 months ago


I'd try redeploying your Redis instance.


ve-jo
HOBBY

2 months 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
HOBBY

2 months 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

2 months 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

2 months ago

Ill check this one


0x5b62656e5d

I'd try redeploying your Redis instance.

kerebere
PROOP

2 months ago

Nah. Tried as well


kerebere

Nah. Tried as well

ve-jo
HOBBY

2 months 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

a month ago

Thanks, this one helped me


Status changed to Solved brody about 2 months ago


Welcome!

Sign in to your Railway account to join the conversation.

Loading...