If you deploy a Node.js application to Namecheap Shared Hosting and it uses Bull, BullMQ, sessions, caching, or another Redis-backed feature, you may discover that a Redis connection which works locally fails in production.
That happened to me. The application deployed successfully, HTTP routes worked, and environment variables loaded correctly—but every queue operation eventually failed with:
MaxRetriesPerRequestError: Reached the max retries per request limit
The underlying error was more useful:
connect ECONNREFUSED <redis-host>:<redis-port>
The fix was not installing Redis inside the shared-hosting account. Instead, I connected the Namecheap-hosted Node.js application to an external Redis server and asked Namecheap Support to permit the required outbound TCP port.
This guide walks through the complete setup and the troubleshooting lessons that mattered.
What You Are Actually Building
On shared hosting, you generally do not control the operating system or run persistent system services such as your own Redis daemon. The practical architecture is:
Browser or API client
|
v
Node.js app on Namecheap Shared Hosting
|
| Outbound TCP connection
v
External Redis server
The Redis server can be:
- A managed Redis service
- Redis running on a VPS or cloud server you control
- Another externally reachable Redis-compatible service
The important requirement is that Namecheap's server must be able to reach the Redis host and port.
Prerequisites
You will need:
- A Node.js application configured through cPanel → Setup Node.js App
- SSH or cPanel Terminal access
- An external Redis instance
- The Redis hostname, port, username, password, and TLS requirements
- A Redis client such as
ioredis
Namecheap's official guide explains how to create the Node.js application, choose its root and startup file, add environment variables, install packages, and restart it: How to work with Node.js App.
1. Create or Obtain an External Redis Instance
Create a Redis database with your chosen provider, or configure Redis on a separate server.
Your provider should give you a connection URL resembling one of these:
redis://default:PASSWORD@HOST:PORT
For a TLS-encrypted connection:
rediss://default:PASSWORD@HOST:PORT
redis:// uses a normal TCP connection. rediss:// tells compatible clients to use TLS. Use the exact scheme supplied by your Redis provider; do not change it by guesswork.
Do not use a provider's HTTP REST URL:
https://example-redis-provider.com
Bull and ioredis require the Redis TCP endpoint.
Secure the Redis server
Never expose an unauthenticated Redis instance to the public internet. Redis warns that an exposed server can allow destructive commands such as FLUSHALL. Use authentication, network restrictions, and TLS where available. See the official Redis security guidance.
If your provider has an IP allowlist, you may need the outgoing public IP of the Namecheap server. From the Namecheap terminal, run:
curl -s https://api.ipify.org
Add that IP to the Redis provider's allowlist. Do not use 0.0.0.0/0 merely to make the connection work.
2. Configure the Node.js Application
For a NestJS application using Bull, install the required packages:
npm install @nestjs/bull bull ioredis
Configure Bull with the connection URL:
import { BullModule } from '@nestjs/bull';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
BullModule.forRoot({
redis: process.env.REDIS_URL,
}),
],
})
export class AppModule {}
For a plain Node.js connection test:
const Redis = require('ioredis');
const redis = new Redis(process.env.REDIS_URL);
redis.ping().then(console.log);
3. Add REDIS_URL in cPanel
Open:
cPanel → Setup Node.js App → Edit application
Under Environment variables, add:
Name: REDIS_URL
Value: redis://default:PASSWORD@HOST:PORT
Use rediss:// if your provider requires TLS.
You may also keep a .env file in the application root:
application-root/
├── app.js
├── package.json
├── .env
└── dist/
The .env file belongs beside app.js and package.json, not inside dist.
Do not commit .env to Git. Add it to .gitignore:
.env
.env.*
!.env.example
If the same variable exists in both cPanel and .env, the value already present in the process environment normally wins. A blank or outdated cPanel value can therefore override the correct value in .env.
After adding or changing environment variables, restart the application from Setup Node.js App.
4. Confirm That the Environment Variable Loads
From the application root in the Namecheap terminal, run this safe check:
node -r dotenv/config -e 'const v=process.env.REDIS_URL; console.log({set:Boolean(v), protocol:v ? v.split(":")[0] : null, length:v ? v.length : 0})'
Example output:
{ set: true, protocol: 'redis', length: 107 }
This confirms that the .env value exists without printing the password.
One subtlety: environment variables configured in cPanel are injected into the Passenger-managed application process. They may not automatically appear in an ordinary SSH shell. The command above explicitly reads the .env file through dotenv.
5. Test the Network Before Testing the Application
First test whether the Redis TCP port is reachable:
nc -vz <redis-host> <redis-port>
Possible results include:
Connection succeeded
or:
Connection refused
A normal ICMP ping is not enough. It only tests whether a host responds to ICMP; it does not prove that Redis is listening or reachable on its TCP port.
Next, test the Redis protocol using the same client library as the application:
node -r dotenv/config -e 'const Redis=require("ioredis"); const r=new Redis(process.env.REDIS_URL,{connectTimeout:5000,maxRetriesPerRequest:1,retryStrategy:()=>null}); r.on("error",()=>{}); r.ping().then(x=>console.log("Redis:",x)).catch(e=>console.error(e.code,e.message)).finally(()=>r.disconnect())'
A successful connection prints:
Redis: PONG
The Redis PING command is specifically intended for testing whether a connection is alive. See the official PING command documentation.
If redis-cli is available, you can also use:
redis-cli -u "$REDIS_URL" PING
Redis documents URI-based connections and notes that rediss is the scheme for TLS: Redis CLI documentation.
6. When It Works Locally but Fails on Namecheap
This was the key production issue in my deployment:
- The Redis test returned
PONGon my local machine. - The same connection returned
ECONNREFUSEDfrom the Namecheap terminal. - The environment variable was present and correctly formatted.
- Namecheap Support opened the required outbound port.
- The connection then worked from production.
If you encounter the same pattern, first check:
- Whether the Redis provider allowlists source IP addresses
- Whether your Redis server's firewall permits the Namecheap server
- Whether a cloud security group permits the Redis port
- Whether Redis is actually listening on the advertised external interface and port
- Whether Namecheap permits outbound TCP traffic to that destination port
If the destination-side settings are correct, contact Namecheap Support with a precise request:
Please confirm whether outbound TCP connections from my shared-hosting server to
<redis-host>:<redis-port>are permitted. My Node.js application requires this connection for Redis.
Include:
- Your Namecheap shared-server hostname
- The destination Redis hostname or IP
- The destination TCP port
- The exact error, such as
ECONNREFUSEDorETIMEDOUT
Never include your Redis password in the support message.
7. Configure Queue Operations to Fail Safely
Redis connectivity is not the only concern. Make sure asynchronous queue operations are awaited.
Avoid this:
this.processPdfQueue.add(jobData);
return {
message: 'Job queued successfully',
};
If Redis is unavailable, the application may report success before the rejected promise is observed. In some Node.js configurations, the unhandled rejection can terminate the process.
Use:
const job = await this.processPdfQueue.add(jobData);
return {
message: 'Job queued successfully',
jobId: job.id,
};
Now the surrounding try/catch can return an honest error response when Redis is unavailable.
Do not treat a larger maxRetriesPerRequest value as the fix for an unreachable Redis server. More retries only postpone the same failure.
8. Read Production Logs
For a Namecheap Node.js application, application and Passenger errors commonly appear in the configured log file, often named stderr.log.
Display recent entries:
tail -n 100 stderr.log
Follow new entries:
tail -f stderr.log
Press Ctrl+C to stop following the file.
You can also inspect:
cPanel → Metrics → Errors
Namecheap documents that this view shows the latest web-server errors in its cPanel overview.
Common Redis Connection Errors
| Error | What it usually means |
|---|---|
ECONNREFUSED |
The host was reached, but the port rejected the connection or nothing was listening |
ETIMEDOUT |
A firewall, security group, routing problem, or unreachable host silently dropped the connection |
ENOTFOUND |
The Redis hostname could not be resolved |
WRONGPASS or authentication error |
The username or password is wrong |
| TLS or socket reset errors | The client and server may disagree about TLS; verify redis:// versus rediss://
|
MaxRetriesPerRequestError |
The client retried a failed request repeatedly; inspect earlier logs for the underlying connection error |
Deployment Checklist
Before calling the setup complete, verify all of the following:
- [ ] Redis is running on an external, reachable server
- [ ] Authentication is enabled
- [ ] TLS is enabled when supported
- [ ]
REDIS_URLuses the provider's TCP endpoint - [ ]
.envis outsidedistand excluded from Git - [ ] The cPanel environment variable is correct
- [ ] The Node.js app was restarted after configuration changes
- [ ]
nc -vz <host> <port>succeeds from Namecheap - [ ] The
ioredistest returnsPONGfrom Namecheap - [ ] Redis allows the Namecheap server's source IP where allowlisting is used
- [ ] Namecheap permits the required outbound destination port
- [ ] Queue operations such as
queue.add()are awaited - [ ] Production logs are available and monitored
Final Takeaway
The hardest part was not the Node.js or Bull configuration. It was identifying where the connection failed.
Checking the problem layer by layer made the answer clear:
- Confirm the environment variable exists.
- Confirm the URL is a Redis TCP URL.
- Test the destination port from the production terminal.
- Run a real Redis
PING. - Compare local and production results.
- Check both destination firewalls and Namecheap's outbound rules.
Once Namecheap permitted the required outbound port, the application connected to Redis and the background jobs started working.
Top comments (0)