REDIS connection issues from local machine

joselvelez
PRO

3 months ago

I'm getting this when I try to connect to redis from localhost: Error: connect ETIMEDOUT at TLSSocket.<anonymous> [rest is truncated for privacy]

Cursor provided the following review of my console logs:

The exceptions.log file shows an entry at Wed May 07 2025 14:51:42 GMT-0300, which corresponds to your latest run (17:51:42 UTC). This log entry also records the same connect ETIMEDOUT error.

The problem is still related to the inability to connect to [url removed] via TLS.

I am running NestJS with BullMQ and Bullboard.

I see this in the console:

```
> nest start

2025-05-07T17:51:31.495Z info: [NestFactory] Starting Nest application... +0ms

2025-05-07T17:51:31.519Z info: [InstanceLoader] PrismaModule dependencies initialized +24ms

2025-05-07T17:51:31.520Z info: [InstanceLoader] LoggingModule dependencies initialized +1ms

2025-05-07T17:51:31.520Z info: [InstanceLoader] BullBoardModule dependencies initialized +0ms

2025-05-07T17:51:31.532Z info: [InstanceLoader] ConfigHostModule dependencies initialized +12ms

2025-05-07T17:51:31.532Z info: [InstanceLoader] BullBoardFeatureModule dependencies initialized +0ms

2025-05-07T17:51:31.533Z info: [InstanceLoader] DiscoveryModule dependencies initialized +1ms

2025-05-07T17:51:31.533Z info: [InstanceLoader] BullBoardRootModule dependencies initialized +0ms

2025-05-07T17:51:31.533Z info: [InstanceLoader] ConfigModule dependencies initialized +0ms

2025-05-07T17:51:31.533Z info: [InstanceLoader] ConfigModule dependencies initialized +0ms

2025-05-07T17:51:31.534Z info: [AppModule] AppModule initialized. +0ms

2025-05-07T17:51:31.534Z info: [AppModule] DIAGNOSTIC - NODE_ENV: development +0ms

2025-05-07T17:51:31.534Z info: [AppModule] DIAGNOSTIC - BullMQ Redis family (derived from env): 0 +0ms

2025-05-07T17:51:31.534Z info: [AppModule] DIAGNOSTIC - REDIS_HOST: [redacted] +0ms

2025-05-07T17:51:31.534Z info: [AppModule] DIAGNOSTIC - REDIS_PORT: [redacted] +0ms

2025-05-07T17:51:31.534Z info: [AppModule] DIAGNOSTIC - REDIS_USERNAME: [redacted] +0ms

2025-05-07T17:51:31.534Z info: [AppModule] DIAGNOSTIC - REDIS_PASSWORD is set: true +0ms

2025-05-07T17:51:31.535Z info: [InstanceLoader] BullModule dependencies initialized +1ms

2025-05-07T17:51:31.536Z info: [AccountsController] FlowProducer initialized (Host: [redacted], Port: [redacted], Username: [redacted], Password Set: true, Family: 0) +1ms

2025-05-07T17:51:31.536Z info: [InstanceLoader] BullModule dependencies initialized +0ms

2025-05-07T17:51:31.540Z info: [RoutesResolver] AppController {/}: +3ms

2025-05-07T17:51:31.541Z info: [RouterExplorer] Mapped {/, GET} route +1ms

2025-05-07T17:51:31.594Z info: AccountImportProcessor initialized and attached to queue: account-import +52ms

2025-05-07T17:51:31.595Z info: [NestApplication] Nest application successfully started +1ms

2025-05-07T17:51:31.596Z info: [NestApplication] Application is running on: http://localhost:3001 +1ms

2025-05-07T17:51:42.017Z error: [BULLMQ WORKER EVENT - ERROR] Worker error for Job ID: N/A, 

Name: N/A, ImportJobId: N/A. Error: connect ETIMEDOUT +10s

["Error: connect ETIMEDOUT\n    at TLSSocket.<anonymous> (/Users/josevelez/Projects/gridl_queue_system/node_modules/ioredis/built/Redis.js:170:41)\n    at Object.onceWrapper (node:events:627:28)\n    at TLSSocket.emit (node:events:513:28)\n    at Socket._onTimeout (node:net:609:8)\n    at listOnTimeout (node:internal/timers:614:17)\n    at process.processTimers (node:internal/timers:549:7)"]
Error: connect ETIMEDOUT

    at TLSSocket.<anonymous> (/Users/josevelez/Projects/gridl_queue_system/node_modules/ioredis/built/Redis.js:170:41)
    at Object.onceWrapper (node:events:627:28)

    at TLSSocket.emit (node:events:513:28)

    at Socket._onTimeout (node:net:609:8)

    at listOnTimeout (node:internal/timers:614:17)

    at process.processTimers (node:internal/timers:549:7) {

  errorno: 'ETIMEDOUT',

  code: 'ETIMEDOUT',

  syscall: 'connect'

}
```

Solved

16 Replies

3 months ago

Hello,

You need to connect to the public host and port without TLS.

Best,
Brody


Status changed to Awaiting User Response Railway 3 months ago


brody

Hello,You need to connect to the public host and port without TLS.Best,Brody

joselvelez
PRO

3 months ago

But that will incur egress fees. I was using the url provided under Settings -> Networking before and it worked. but today it stopped working.


Status changed to Awaiting Railway Response Railway 3 months ago


joselvelez
PRO

3 months ago

any idea? I'm stuck and cannot connect to my redis instance from localhost.


joselvelez
PRO

3 months ago

I've tried everything with no luck. I tried setting family: 0 and family: 4 and still no luck. I'm using TLS.

im connecting with this custom method:

```

export function createBullMqConnectionOptions(
  configService: ConfigService,
): ConnectionOptions {
  const host = configService.get<string>('REDIS_HOST');
  const port = configService.get<number>('REDIS_PORT');
  const username = configService.get<string | undefined>('REDIS_USERNAME');
  const password = configService.get<string | undefined>('REDIS_PASSWORD');
  const familyEnvValue = configService.get<string | undefined>('REDIS_FAMILY');
  let family: number = 0; // Default to 0 (IPv4 then IPv6)

  if (familyEnvValue !== undefined) {
    const parsedFamily = parseInt(familyEnvValue, 10);
    if (!isNaN(parsedFamily) && [0, 4, 6].includes(parsedFamily)) {
      family = parsedFamily;
    } else {
      logger.warn(
        `Invalid REDIS_FAMILY value: "${familyEnvValue}". Expected "0", "4", or "6". Defaulting to ${family}.`,
      );
    }
  }

  const connectionOptions: ConnectionOptions = {
    host,
    port,
    username: username || undefined, // Ensure undefined if empty string
    password: password || undefined, // Ensure undefined if empty string
    family,
    // If host is not localhost, enable TLS and set servername to the host for SNI
    tls: host !== 'localhost' ? { servername: host } : undefined,
  };

```


joselvelez
PRO

3 months ago

Below is my console log:

025-05-07T19:25:57.959Z error: [BULLMQ WORKER EVENT - ERROR] Worker error for Job ID: N/A, Name: N/A, ImportJobId: N/A. Error: connect ETIMEDOUT +10s

["Error: connect ETIMEDOUT\n at TLSSocket.<anonymous> (/[redacted]/node_modules/ioredis/built/Redis.js:170:41)\n at Object.onceWrapper (node:events:627:28)\n at TLSSocket.emit (node:events:513:28)\n at Socket._onTimeout (node:net:609:8)\n at listOnTimeout (node:internal/timers:614:17)\n at process.processTimers (node:internal/timers:549:7)"]

Error: connect ETIMEDOUT

at TLSSocket.<anonymous> (/[redacted]/node_modules/ioredis/built/Redis.js:170:41)

at Object.onceWrapper (node:events:627:28)

at TLSSocket.emit (node:events:513:28)

at Socket._onTimeout (node:net:609:8)

at listOnTimeout (node:internal/timers:614:17)

at process.processTimers (node:internal/timers:549:7) {

errorno: 'ETIMEDOUT',

code: 'ETIMEDOUT',

syscall: 'connect'

}

2025-05-07T19:25:57.964Z error: [BULLMQ WORKER EVENT - ERROR] Worker error for Job ID: N/A, Name: N/A, ImportJobId: N/A. Error: connect ETIMEDOUT +5ms

["Error: connect ETIMEDOUT\n at TLSSocket.<anonymous> (/[redacted]/node_modules/ioredis/built/Redis.js:170:41)\n at Object.onceWrapper (node:events:627:28)\n at TLSSocket.emit (node:events:513:28)\n at Socket._onTimeout (node:net:609:8)\n at listOnTimeout (node:internal/timers:614:17)\n at process.processTimers (node:internal/timers:549:7)"]


joselvelez

I've tried everything with no luck. I tried setting family: 0 and family: 4 and still no luck. I'm using TLS.im connecting with this custom method:```export function createBullMqConnectionOptions( configService: ConfigService, ): ConnectionOptions { const host = configService.get<string>('REDIS_HOST'); const port = configService.get<number>('REDIS_PORT'); const username = configService.get<string | undefined>('REDIS_USERNAME'); const password = configService.get<string | undefined>('REDIS_PASSWORD'); const familyEnvValue = configService.get<string | undefined>('REDIS_FAMILY'); let family: number = 0; // Default to 0 (IPv4 then IPv6) if (familyEnvValue !== undefined) { const parsedFamily = parseInt(familyEnvValue, 10); if (!isNaN(parsedFamily) && [0, 4, 6].includes(parsedFamily)) { family = parsedFamily; } else { logger.warn( `Invalid REDIS_FAMILY value: "${familyEnvValue}". Expected "0", "4", or "6". Defaulting to ${family}.`, ); } } const connectionOptions: ConnectionOptions = { host, port, username: username || undefined, // Ensure undefined if empty string password: password || undefined, // Ensure undefined if empty string family, // If host is not localhost, enable TLS and set servername to the host for SNI tls: host !== 'localhost' ? { servername: host } : undefined, };```

3 months ago

What exactly are you passing as connection options to BullMQ?

https://docs.railway.com/reference/errors/enotfound-redis-railway-internal#using-bullmq

Does that not work?


Status changed to Awaiting User Response Railway 3 months ago


ray-chen

What exactly are you passing as connection options to BullMQ?https://docs.railway.com/reference/errors/enotfound-redis-railway-internal#using-bullmqDoes that not work?

joselvelez
PRO

3 months ago

When I use this it works:

export function createBullMqConnectionOptions(
  configService: ConfigService,
): ConnectionOptions {
  const redisUrlString = configService.get<string>('REDIS_URL');

  if (!redisUrlString) {
    throw new Error('REDIS_URL is not defined in environment variables.');
  }
  const redisUrl = new URL(redisUrlString);
  const host = redisUrl.hostname;
  const port = Number(redisUrl.port);
  const username = redisUrl.username || undefined;
  const password = redisUrl.password || undefined;

  const connectionOptions: ConnectionOptions = {
    host,
    port,
    username,
    password,
    tls: redisUrl.protocol === 'rediss:' ? { servername: host } : undefined,
  };
  return connectionOptions;
}

but when I use this, it does not

export function createBullMqConnectionOptions(
  configService: ConfigService,
): ConnectionOptions {
  const host = configService.get<string>('REDIS_HOST');
  const port = configService.get<number>('REDIS_PORT');
  const username = configService.get<string | undefined>('REDIS_USERNAME');
  const password = configService.get<string | undefined>('REDIS_PASSWORD');
  const familyEnvValue = configService.get<string | undefined>('REDIS_FAMILY');
  let family: number = 0; // Default to 0 (IPv4 then IPv6)

  if (familyEnvValue !== undefined) {
    const parsedFamily = parseInt(familyEnvValue, 10);
    if (!isNaN(parsedFamily) && [0, 4, 6].includes(parsedFamily)) {
      family = parsedFamily;
    } else {
      logger.warn(
        `Invalid REDIS_FAMILY value: "${familyEnvValue}". Expected "0", "4", or "6". Defaulting to ${family}.`,
      );
    }
  }

  const connectionOptions: ConnectionOptions = {
    host,
    port,
    username: username || undefined, // Ensure undefined if empty string
    password: password || undefined, // Ensure undefined if empty string
    family,
    // If host is not localhost, enable TLS and set servername to the host for SNI
    tls: host && host !== 'localhost' ? { servername: host } : undefined,
  };
  return connectionOptions;
}

The first is using the URL for public network

  • My understanding is that using this url will incur egress charges

  • This works on my local machine

  • This does not work on my NestJS instance on Railway within the same project

I will continue in a new message due to character constraints...


Status changed to Awaiting Railway Response Railway 3 months ago


3 months ago

Yes it will incur egress, but you cannot connect to the private domain from your own computer.


Status changed to Awaiting User Response Railway 3 months ago


joselvelez

When I use this it works:export function createBullMqConnectionOptions( configService: ConfigService, ): ConnectionOptions { const redisUrlString = configService.get<string>('REDIS_URL'); if (!redisUrlString) { throw new Error('REDIS_URL is not defined in environment variables.'); } const redisUrl = new URL(redisUrlString); const host = redisUrl.hostname; const port = Number(redisUrl.port); const username = redisUrl.username || undefined; const password = redisUrl.password || undefined; const connectionOptions: ConnectionOptions = { host, port, username, password, tls: redisUrl.protocol === 'rediss:' ? { servername: host } : undefined, }; return connectionOptions; }but when I use this, it does notexport function createBullMqConnectionOptions( configService: ConfigService, ): ConnectionOptions { const host = configService.get<string>('REDIS_HOST'); const port = configService.get<number>('REDIS_PORT'); const username = configService.get<string | undefined>('REDIS_USERNAME'); const password = configService.get<string | undefined>('REDIS_PASSWORD'); const familyEnvValue = configService.get<string | undefined>('REDIS_FAMILY'); let family: number = 0; // Default to 0 (IPv4 then IPv6) if (familyEnvValue !== undefined) { const parsedFamily = parseInt(familyEnvValue, 10); if (!isNaN(parsedFamily) && [0, 4, 6].includes(parsedFamily)) { family = parsedFamily; } else { logger.warn( `Invalid REDIS_FAMILY value: "${familyEnvValue}". Expected "0", "4", or "6". Defaulting to ${family}.`, ); } } const connectionOptions: ConnectionOptions = { host, port, username: username || undefined, // Ensure undefined if empty string password: password || undefined, // Ensure undefined if empty string family, // If host is not localhost, enable TLS and set servername to the host for SNI tls: host && host !== 'localhost' ? { servername: host } : undefined, }; return connectionOptions; }The first is using the URL for public network.env using REDIS_URL: redis://default:*******@switchback.proxy.rlwy.net:10998My understanding is that using this url will incur egress chargesThis works on my local machineThis does not work on my NestJS instance on Railway within the same projectI will continue in a new message due to character constraints...

joselvelez
PRO

3 months ago

The second is using the address found under REDIS -> Settings -> Networking -> Public Networking

  • .env using

  • This did not work on my local machine

  • This did work (for a while) on my Railway NestJS instance within the same project.

What I do not understand:

What is this address for? Can I not connect from my local machine with this?

I am confused with the different urls available.

Attachments


Status changed to Awaiting Railway Response Railway 3 months ago


3 months ago

That is the public host and public port (5 digit number).

The data tab uses those to connect, if the data tab can connect the database is publicly accessible and is working as intended.


Status changed to Awaiting User Response Railway 3 months ago


brody

That is the public host and public port (5 digit number).The data tab uses those to connect, if the data tab can connect the database is publicly accessible and is working as intended.

joselvelez
PRO

3 months ago

Ok, so how do I get my NestJS instance in the same project to connect successfully without using the pubic address that incurs egress charges? My NestJS instance keeps crashing


Status changed to Awaiting Railway Response Railway 3 months ago


3 months ago

That is covered in the link Ray provided above.


Status changed to Awaiting User Response Railway 3 months ago


joselvelez
PRO

3 months ago

No, that uses the PUBLIC address that incurs egress charges. I want to connect INTERNALLY within the same project.


Status changed to Awaiting Railway Response Railway 3 months ago


joselvelez
PRO

3 months ago

I am able to connect from local machine now, but my NestJS instance in my railway project continues to crash. I've tried all the different hosts with no success.

  • redis

  • ${{ Redis.REDIS_URL }}

  • redis://default:*****@redis.railway.internal:6379

  • redis.railway.internal

None of these is working


3 months ago

The example code in Ray's link is to help you use BullMQ with the private network.


Status changed to Awaiting User Response Railway 3 months ago


joselvelez
PRO

3 months ago

Ok, I have it all working now on local and within the project. For anyone else that might struggle with this, I used this custom helper to handle the connection based on the environment, since you basically have two different configs (one for private on Railway and one for public when on local machine).

Below is the helper method I used inside my NestJS Project

import IORedis, { RedisOptions } from 'ioredis';
import { ConfigService } from '@nestjs/config';
import { Logger } from '@nestjs/common';
import { URL } from 'url';

export function createBullMqConnection(configService: ConfigService): IORedis {
  const isLocal = process.env.NODE_ENV === 'development';

  if (isLocal) {
    const redisUrlString = configService.get<string>('REDIS_URL_PUBLIC');
    if (!redisUrlString) {
      throw new Error(
        'REDIS_URL_PUBLIC is not defined in environment variables.',
      );
    }

    const redisUrl = new URL(redisUrlString);

    const options: RedisOptions = {
      host: redisUrl.hostname,
      port: Number(redisUrl.port),
      username: redisUrl.username || undefined,
      password: redisUrl.password || undefined,
      tls:
        redisUrl.protocol === 'rediss:'
          ? { servername: redisUrl.hostname }
          : undefined,
      maxRetriesPerRequest: null,
    };

    Logger.log(
      `Using EXTERNAL Redis connection (Host: ${options.host}, Port: ${options.port}, TLS: ${!!options.tls})`,
    );

    return new IORedis(options);
  } else {
    const redisUrlString = configService.get<string>('REDIS_URL_PRIVATE');
    if (!redisUrlString) {
      throw new Error(
        'REDIS_URL_PRIVATE is not defined in environment variables.',
      );
    }

    const redisUrl = new URL(redisUrlString);

    const options: RedisOptions = {
      host: redisUrl.hostname,
      port: Number(redisUrl.port),
      family: 0, // IPv4/IPv6 Dual Stack Lookup
      username: redisUrl.username || undefined,
      password: redisUrl.password || undefined,
      maxRetriesPerRequest: null,
    };

    Logger.log(
      `Using INTERNAL Redis connection (Host: ${options.host}, Port: ${options.port})`,
    );

    return new IORedis(options);
  }
}

I saved this to a git repo with some documentation for anyone that wants to use it. I hope this helps.

https://github.com/joselvelez/railway_redis_bullmq_connection_helper/tree/main

If I made any mistakes, please let me know.


Status changed to Awaiting Railway Response Railway 3 months ago


Status changed to Solved joselvelez 3 months ago


REDIS connection issues from local machine - Railway Help Station