Skip to content

Fix: Redis ECONNREFUSED – Connection Refused on localhost:6379

FixDevs ·

Quick Answer

How to fix the Redis ECONNREFUSED error when your application cannot connect to the Redis server on localhost:6379 or a remote host. Covers Redis not running, wrong host/port, Docker networking, firewall, AUTH required, maxclients, and TLS configuration.

The Error

You try to connect to Redis and get:

Error: connect ECONNREFUSED 127.0.0.1:6379

Or one of these variations:

Error: connect ECONNREFUSED ::1:6379
Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379
Could not connect to Redis at 127.0.0.1:6379: Connection refused
NOAUTH Authentication required
ERR max number of clients reached
Error: Redis connection lost and command aborted. It might have been processed.

All of these mean the same underlying problem: your client cannot establish or maintain a connection to the Redis server. Either Redis is not running, the connection details are wrong, something is blocking the connection, or Redis is rejecting it for a specific reason.

Why This Happens

Redis listens for connections on port 6379 by default. When your client sends a TCP connection request and nothing is listening at that address and port, the operating system responds with a “connection refused” error, which surfaces as ECONNREFUSED in Node.js and similar environments.

Common causes:

  • Redis is not running. The service was never started, crashed, or was stopped during a system update. This is the number one cause.
  • Wrong host or port. Your application is trying to connect to localhost:6379 but Redis is listening on a different interface or port.
  • Docker networking. Your app is running inside a Docker container and localhost resolves to the container itself, not the host machine or the Redis container.
  • Firewall blocking port 6379. A firewall rule is silently dropping or rejecting the connection before it reaches Redis.
  • Redis requires authentication. Redis is reachable but requires a password via the AUTH command, and your client is not sending one.
  • maxclients limit reached. Redis has hit its maximum number of simultaneous client connections and is refusing new ones.
  • TLS/SSL mismatch. Redis is configured for TLS-only connections but your client is connecting without TLS, or the other way around.
  • Redis is bound to a specific interface. By default, Redis binds to 127.0.0.1, rejecting connections from other machines or from Docker containers using the host’s network IP.
  • IPv6 vs IPv4 resolution. On some systems, localhost resolves to ::1 (IPv6) but Redis is only listening on 127.0.0.1 (IPv4).

Fix 1: Start Redis

The most common cause. Redis simply is not running.

Linux (systemd):

sudo systemctl start redis

On some distributions, the service is called redis-server:

sudo systemctl start redis-server

Check the status:

sudo systemctl status redis

If it is not enabled to start on boot:

sudo systemctl enable redis

macOS (Homebrew):

brew services start redis

Check the status:

brew services list | grep redis

Windows:

If you installed Redis via the official Windows port or Memurai, open Services (Win+R, type services.msc), find the Redis service, right-click, and select Start.

Or from an elevated Command Prompt:

net start Redis

For WSL-based Redis:

sudo service redis-server start

Verify Redis is listening:

redis-cli ping

If Redis is running, you get:

PONG

If it is not running, you get:

Could not connect to Redis at 127.0.0.1:6379: Connection refused

You can also check the port directly:

# Linux / macOS
ss -tlnp | grep 6379

# Windows (PowerShell)
netstat -an | findstr 6379

If nothing is listening on 6379, Redis is not running. Check the logs to find out why:

# Linux
sudo tail -50 /var/log/redis/redis-server.log

# macOS (Homebrew)
tail -50 /opt/homebrew/var/log/redis.log

Common startup failures:

  • Data directory permissions. Redis cannot write to its data directory. Fix with:
sudo chown -R redis:redis /var/lib/redis
sudo chmod 770 /var/lib/redis
  • Corrupt RDB or AOF file. Redis refuses to start if its persistence file is corrupted. Check the logs for messages like Bad data format or Bad file format reading the append only file. You can attempt a repair:
redis-check-rdb /var/lib/redis/dump.rdb
redis-check-aof --fix /var/lib/redis/appendonly.aof
  • Another process is using port 6379. Check what is using the port:
sudo lsof -i :6379

Kill the conflicting process or change the Redis port in redis.conf.

Fix 2: Check the Host and Port Configuration

Your application may be connecting to the wrong address or port. Redis defaults to 127.0.0.1:6379, but this can be changed in redis.conf.

Check what Redis is actually listening on:

redis-cli INFO server | grep tcp_port
redis-cli INFO server | grep bind

Or look at the config file directly:

grep -E "^(bind|port)" /etc/redis/redis.conf

A typical config looks like:

bind 127.0.0.1 -::1
port 6379

If Redis is listening on a non-default port, update your application’s connection configuration:

// Node.js with ioredis
const Redis = require('ioredis');
const redis = new Redis({
  host: '127.0.0.1',
  port: 6380 // match whatever Redis is actually using
});
# Python with redis-py
import redis
r = redis.Redis(host='127.0.0.1', port=6380)

If your connection details come from environment variables, make sure those variables are actually loaded. A common mistake is forgetting to call dotenv.config() before reading process.env.REDIS_URL. If the variable comes back as undefined, your Redis client falls back to defaults that may not match your setup. See Fix: Environment Variable Is Undefined for more on this.

Fix 3: Fix Docker Networking

If your application runs inside a Docker container and Redis runs on the host machine or in another container, localhost inside your container refers to the container itself, not the host or other containers. This is one of the most common causes of ECONNREFUSED in containerized environments.

Connecting to Redis on the host from a container

Docker Desktop (macOS/Windows):

redis://host.docker.internal:6379

Linux:

docker run --add-host=host.docker.internal:host-gateway myapp

Then use host.docker.internal as the Redis host in your application.

Connecting between containers with docker-compose

Use the service name as the hostname, not localhost:

services:
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

  app:
    build: .
    environment:
      REDIS_URL: redis://redis:6379
    depends_on:
      - redis

volumes:
  redis-data:

The hostname is redis (the service name), not localhost. Your app connects to redis:6379, and Docker’s internal DNS resolves it to the Redis container’s IP.

Redis container is not ready yet

If your app starts before Redis finishes initializing, the connection fails. Add a health check so that depends_on waits for Redis to be truly ready:

services:
  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5

  app:
    build: .
    environment:
      REDIS_URL: redis://redis:6379
    depends_on:
      redis:
        condition: service_healthy

Containers on different networks

If your app container and Redis container are on different Docker networks, they cannot reach each other. Make sure both services share the same network:

services:
  redis:
    image: redis:7-alpine
    networks:
      - backend

  app:
    build: .
    networks:
      - backend

networks:
  backend:

For more on Docker Compose startup and networking problems, see Fix: Docker Compose Up Errors and Fix: Docker Container Not Connecting.

Real-world scenario: In Docker Compose setups, the most common mistake is using localhost or 127.0.0.1 as the Redis host from your application container. Inside a container, localhost refers to the container itself — not the host machine or other containers. Always use the Docker Compose service name (e.g., redis) as the hostname.

Fix 4: Configure the Firewall

A firewall may be silently dropping connections to port 6379 before they reach Redis. This is especially common on cloud servers (AWS, GCP, Azure) where security groups or firewall rules are restrictive by default.

UFW (Ubuntu/Debian):

sudo ufw allow 6379/tcp
sudo ufw reload

firewalld (RHEL/Fedora/CentOS):

sudo firewall-cmd --add-port=6379/tcp --permanent
sudo firewall-cmd --reload

iptables:

sudo iptables -A INPUT -p tcp --dport 6379 -j ACCEPT

AWS Security Groups:

In the AWS Console, go to your instance’s security group and add an inbound rule for TCP port 6379 from your application’s IP or security group.

Important: Never expose Redis port 6379 to the public internet without authentication and encryption. Redis has no built-in protection against unauthorized access by default. If you need remote access, use SSH tunneling or a VPN:

# SSH tunnel to access remote Redis locally
ssh -L 6379:127.0.0.1:6379 user@remote-server

Then connect to localhost:6379 on your local machine, and the traffic is forwarded through the SSH tunnel.

Fix 5: Set Up Redis Authentication

If Redis requires a password, connecting without one produces:

NOAUTH Authentication required

Or if you provide the wrong password:

WRONGPASS invalid username-password pair or user is disabled

Check if AUTH is enabled

Look at redis.conf:

grep "^requirepass" /etc/redis/redis.conf

If it returns something like requirepass mysecretpassword, authentication is enabled.

In Redis 6+, ACLs (Access Control Lists) replace the simple requirepass mechanism. Check ACL users:

redis-cli ACL LIST

Connect with authentication

redis-cli:

redis-cli -a mysecretpassword

Or after connecting:

AUTH mysecretpassword

With Redis 6+ ACLs:

AUTH username password

Node.js (ioredis):

const Redis = require('ioredis');

// Simple password
const redis = new Redis({
  host: '127.0.0.1',
  port: 6379,
  password: 'mysecretpassword'
});

// Redis 6+ ACL with username
const redis = new Redis({
  host: '127.0.0.1',
  port: 6379,
  username: 'myuser',
  password: 'mysecretpassword'
});

Using a Redis URL:

// Without username (pre-Redis 6)
const redis = new Redis('redis://:[email protected]:6379');

// With username (Redis 6+ ACL)
const redis = new Redis('redis://myuser:[email protected]:6379');

Python (redis-py):

import redis

r = redis.Redis(
    host='127.0.0.1',
    port=6379,
    password='mysecretpassword',
    username='myuser'  # Redis 6+ ACL only
)

If your password is stored in an environment variable, make sure it is loaded correctly. A missing or empty password variable will cause silent authentication failures. See Fix: Environment Variable Is Undefined to debug this.

Fix 6: Handle maxclients Limit

When Redis hits its maxclients limit, new connections are refused:

ERR max number of clients reached

Check the current limit and active connections

redis-cli INFO clients

Look for:

connected_clients:150
maxclients:128

If connected_clients is at or near maxclients, you have hit the limit.

Increase maxclients

In redis.conf:

maxclients 10000

Or set it at runtime without restarting:

redis-cli CONFIG SET maxclients 10000

Note that the OS file descriptor limit (ulimit -n) must be higher than maxclients + 32 (Redis reserves 32 file descriptors for internal use). Increase it if needed:

# Check current limit
ulimit -n

# Set temporarily
ulimit -n 65535

For a persistent change on Linux, add to /etc/security/limits.conf:

redis soft nofile 65535
redis hard nofile 65535

And for systemd-managed Redis, create an override:

sudo systemctl edit redis

Add:

[Service]
LimitNOFILE=65535

Fix connection leaks

The real problem is usually not a low maxclients value but a connection leak in your application. Common causes:

  • Creating a new Redis connection for every request instead of reusing a single client or connection pool.
  • Not closing connections in serverless functions. AWS Lambda and similar environments reuse containers, and connections pile up.
  • Missing error handlers. When a connection errors out without being caught, the socket may linger.

Check for idle connections:

redis-cli CLIENT LIST

Look for clients with a high idle value (in seconds). Kill idle clients with:

redis-cli CLIENT KILL ID <id>

Or configure Redis to close idle connections automatically:

timeout 300

This closes client connections that have been idle for 300 seconds.

Fix 7: Fix TLS/SSL Configuration

Redis 6+ supports TLS natively. If your Redis server requires TLS and your client connects without it (or the other way around), the connection fails silently and surfaces as ECONNREFUSED or a timeout.

Check if Redis uses TLS

Look at redis.conf:

grep -E "^(tls-port|tls-cert-file|tls-key-file)" /etc/redis/redis.conf

If tls-port is set (commonly to 6380), Redis expects TLS on that port. The regular port (6379) may be disabled entirely with port 0.

Connect with TLS

redis-cli:

redis-cli --tls --cert /path/to/client.crt --key /path/to/client.key --cacert /path/to/ca.crt -p 6380

Node.js (ioredis):

const Redis = require('ioredis');
const fs = require('fs');

const redis = new Redis({
  host: '127.0.0.1',
  port: 6380,
  tls: {
    ca: fs.readFileSync('/path/to/ca.crt'),
    cert: fs.readFileSync('/path/to/client.crt'),
    key: fs.readFileSync('/path/to/client.key')
  }
});

For Redis services that use TLS on the standard port with publicly trusted certificates (like AWS ElastiCache or Upstash), you typically only need:

const redis = new Redis({
  host: 'your-redis-host.cache.amazonaws.com',
  port: 6379,
  tls: {},
  password: 'your-auth-token'
});

Passing an empty tls: {} object enables TLS without requiring custom certificates.

Using a rediss:// URL:

The rediss:// scheme (note the double s) indicates a TLS connection:

const redis = new Redis('rediss://:password@your-redis-host:6380');

Python (redis-py):

import redis

r = redis.Redis(
    host='127.0.0.1',
    port=6380,
    password='mysecretpassword',
    ssl=True,
    ssl_certfile='/path/to/client.crt',
    ssl_keyfile='/path/to/client.key',
    ssl_ca_certs='/path/to/ca.crt'
)

Self-signed certificate errors

If you get certificate verification errors with a self-signed cert in development:

const redis = new Redis({
  host: '127.0.0.1',
  port: 6380,
  tls: {
    rejectUnauthorized: false // Development only!
  }
});

Never disable certificate verification in production. It makes you vulnerable to man-in-the-middle attacks.

Fix 8: Update the Bind Address

By default, Redis binds to 127.0.0.1, which means it only accepts connections from the local machine. If your application runs on a different machine (or in a Docker container accessing the host network), the connection is refused.

Check the current bind address:

grep "^bind" /etc/redis/redis.conf

To accept connections from all interfaces:

bind 0.0.0.0

Or to accept connections from specific interfaces:

bind 127.0.0.1 192.168.1.100

After changing redis.conf, restart Redis:

sudo systemctl restart redis

Warning: If you bind to 0.0.0.0, make sure requirepass or ACLs are enabled. Also enable protected-mode as an additional safeguard:

protected-mode yes

With protected-mode yes, Redis rejects connections from external interfaces unless a password is set. This prevents accidentally exposing an unprotected Redis instance to the network.

Still Not Working?

IPv6 vs IPv4

On some systems, localhost resolves to ::1 (IPv6) instead of 127.0.0.1 (IPv4). Redis may only be listening on IPv4.

Error: connect ECONNREFUSED ::1:6379

Fix by using 127.0.0.1 explicitly instead of localhost:

const redis = new Redis({
  host: '127.0.0.1', // not 'localhost'
  port: 6379
});

Or configure Redis to listen on both IPv4 and IPv6:

bind 127.0.0.1 ::1

Redis Sentinel or Cluster misconfiguration

If you are using Redis Sentinel for high availability, make sure your client is connecting through the Sentinel, not directly to a replica:

const redis = new Redis({
  sentinels: [
    { host: 'sentinel-1', port: 26379 },
    { host: 'sentinel-2', port: 26379 },
    { host: 'sentinel-3', port: 26379 }
  ],
  name: 'mymaster', // Sentinel master name
  password: 'redis-password'
});

For Redis Cluster:

const Redis = require('ioredis');

const cluster = new Redis.Cluster([
  { host: 'node-1', port: 6379 },
  { host: 'node-2', port: 6379 },
  { host: 'node-3', port: 6379 }
]);

If the cluster topology changed (nodes added or removed) and your client has stale configuration, it will try to connect to nodes that no longer exist. Restart your application to force a topology refresh.

Connection timeouts vs connection refused

If you get a timeout instead of ECONNREFUSED, the problem is different. ECONNREFUSED means a TCP RST was received (nothing is listening). A timeout means the packet was sent but no response came back, which usually points to a firewall dropping packets or a network routing issue.

Add a connectTimeout to surface these faster:

const redis = new Redis({
  host: '127.0.0.1',
  port: 6379,
  connectTimeout: 5000, // fail after 5 seconds instead of hanging
  retryStrategy(times) {
    const delay = Math.min(times * 200, 5000);
    return delay; // retry with increasing delay, max 5 seconds
  }
});

Redis crashed and won’t restart

Check the Redis log for the reason:

sudo journalctl -u redis --no-pager -n 50

Common crash causes:

  • Out of memory. Redis stores everything in RAM. If it exceeds available memory, the OS OOM killer terminates it. Set maxmemory in redis.conf to prevent this:
maxmemory 256mb
maxmemory-policy allkeys-lru
  • Corrupt persistence file. As mentioned in Fix 1, use redis-check-rdb or redis-check-aof --fix to repair.

  • Huge pages warning. Redis logs may show a warning about Transparent Huge Pages (THP). Disable THP:

echo never > /sys/kernel/mm/transparent_hugepage/enabled

Managed Redis services (ElastiCache, Cloud Memorystore, Upstash)

If you are using a managed Redis service, the connection details are different from a local Redis install:

  • AWS ElastiCache is only reachable from within the same VPC. You cannot connect from your local machine without an SSH tunnel or VPN.
  • GCP Cloud Memorystore requires the connecting service to be in the same VPC or to use a private service connection.
  • Upstash and Redis Cloud are accessible over the internet but require TLS and authentication.

For ElastiCache, a common pattern is to SSH tunnel through a bastion host:

ssh -L 6379:your-cluster.abc123.cache.amazonaws.com:6379 ec2-user@bastion-host

Then connect to localhost:6379 locally.

If your Nginx reverse proxy sits in front of an app that uses Redis, a Redis connection failure can cascade into an Nginx 502 Bad Gateway error for end users. Always check Redis connectivity first when debugging 502 errors from backend services.

For similar database connection troubleshooting, see Fix: MongoDB ECONNREFUSED. If your system is hitting file descriptor limits, see Fix: ENOSPC System Limit for File Watchers.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles