Redis Connection Drops on Railway During Deploys — Graceful Reconnection Guide

Redis connection drops on Railway during deploys produce the same predictable pattern almost every time: a short burst of connection errors in the logs, lasting a handful of seconds, clearing up right as the new instance finishes booting. Most of the time, that's not a bug at all — it's exactly what happens when Railway terminates your old instance and Redis loses the connection it was holding. The actual problem, when there is one, is usually that the app isn't configured to treat that brief gap as recoverable, rather than something is wrong with Redis itself.
Short answer: a brief connection drop during every deploy is expected Railway behavior, not a Redis problem — the fix is configuring ioredis with a sensible retryStrategy and connectTimeout so your app reconnects gracefully within that window, and separately monitoring for disruptions that last longer than a deploy actually takes, which is the real signal worth alerting on.

Why This Happens — and Why It's Usually Fine
Railway's own documentation on deployments confirms the mechanism: a deploy terminates your service's previous running instance while the new one starts up. If your app (or a BullMQ worker sharing the same connection) holds an active Redis connection at that exact moment, that connection drops — briefly, predictably, and specifically correlated with your own deploy timeline. This is the platform doing exactly what a rolling restart is supposed to do. The question worth asking isn't "why did this happen" — it's "is my app configured to treat a few seconds of disconnection as something to recover from automatically, or as something that needs a human to notice and restart things manually."
(If you've been treating every deploy-time Redis error as an incident worth investigating — that's understandable the first few times, and unsustainable as a long-term habit. Check whether it clears within a few seconds and lines up with a deploy you just triggered before treating it as anything more than expected noise.)
Fix 1: Configure ioredis's retryStrategy for Fast, Bounded Recovery
The direct fix is a reconnect strategy tuned for exactly this scenario — quick initial retries, capped so it doesn't spiral into hammering Redis if something genuinely more serious is happening:
1// redis-connection.ts
2import Redis from 'ioredis';
3
4const redis = new Redis({
5 host: process.env.REDIS_HOST,
6 port: 6379,
7 connectTimeout: 10_000,
8 retryStrategy(times) {
9 // Fast initial retries, capped at 2 seconds between attempts
10 const delay = Math.min(times * 200, 2_000);
11 return delay;
12 },
13});
14
15redis.on('error', (err) => {
16 console.error('Redis connection error (may be transient):', err.message);
17});ioredis's own CommonRedisOptions reference documents retryStrategy's exact signature: it receives the number of the current attempt and should return the delay in milliseconds before the next one, or undefined/void to stop retrying entirely. Capping the delay at a couple of seconds means the client keeps trying at a reasonable pace through a deploy's brief gap, without escalating into a long backoff that would make recovery feel sluggish once Redis is actually back. ioredis's own repository has further examples of connection event handling worth reviewing if your setup needs more than the basics shown here.

Fix 2: Make Sure the error Handler Exists at All
This part is easy to skip and has nothing to do with tuning — an ioredis client emitting an error event with no listener attached can crash your Node process outright, turning a recoverable few-second blip into an actual downtime incident because the process itself died rather than reconnecting. The redis.on('error', ...) handler shown above isn't optional polish; without it, even a perfectly tuned retryStrategy doesn't matter, because the process crashes before it gets the chance to use it.
Fix 3: Monitor Duration, Not the First Error Event
The mistake worth avoiding is treating the first Redis error during a deploy as something to page someone about. A connection blip that clears in a few seconds and lines up with your own deploy timeline is noise; a disruption that keeps producing errors well past how long your deploys actually take is a real signal:
1// redis-connection.ts — track disruption duration, not just error occurrence
2let disruptionStart: number | null = null;
3const DEPLOY_WINDOW_MS = 30_000; // generous upper bound for how long a deploy restart takes
4
5redis.on('error', () => {
6 if (!disruptionStart) disruptionStart = Date.now();
7 if (Date.now() - disruptionStart > DEPLOY_WINDOW_MS) {
8 console.error('Redis disruption has exceeded expected deploy window — investigate');
9 }
10});
11
12redis.on('connect', () => {
13 disruptionStart = null;
14});This distinguishes "expected, ignore it" from "actually worth waking someone up for" using the one signal that reliably tells them apart: how long the disruption has actually lasted, measured against how long your own deploys normally take.

The Opinion Part
Here's the position worth stating plainly: not every error in your logs is an incident, and treating every one as equally urgent trains a team to either panic constantly or ignore everything — both bad outcomes. A brief, deploy-correlated Redis blip that your reconnect logic already handles gracefully doesn't need a Slack alert; it needs to be invisible, which is the entire point of configuring retryStrategy correctly in the first place. Reserve genuine alerting for the signal that actually distinguishes a real problem — duration past the window you'd expect — rather than the mere presence of an error event that your own architecture already expects and recovers from routinely.
Conclusion
If Redis connections are dropping during every Railway deploy, that's very likely expected behavior from a rolling restart, not a database problem. Configure retryStrategy and connectTimeout for fast, bounded recovery, make sure an error handler actually exists so a transient blip can't crash your process outright, and monitor for disruptions that exceed your normal deploy window rather than reacting to the first error line.
If BullMQ workers specifically are the piece affected by this and jobs seem to stall rather than just log a brief error, our BullMQ jobs stuck waiting guide covers that adjacent failure mode, and if the underlying issue turns out to be Railway's IPv6-default private network rather than a routine restart, our dedicated guide on that covers the connection-level fix directly.
Configure the reconnect logic once, and let deploys go back to being the routine, invisible thing they were always supposed to be.
Frequently Asked Questions
Because a deploy on Railway terminates the previous instance of your service while the new one starts, and if your app or a BullMQ worker holds an active Redis connection at that moment, that connection drops — briefly and predictably. This is expected platform behavior during a rolling restart, not a sign that Redis or Railway is malfunctioning.
Provide a custom retryStrategy function that returns an increasing but capped delay in milliseconds between reconnection attempts, and set a reasonable connectTimeout so a single attempt doesn't hang indefinitely. A capped exponential backoff — retrying quickly at first, then settling into a steady interval — recovers fast from the few-second gap a deploy creates without hammering Redis with reconnect attempts.
Mostly, yes, once the underlying ioredis connection is configured with a sensible retryStrategy — BullMQ relies on that same connection and will resume processing once it reconnects. What it won't do on its own is distinguish a routine few-second gap from a genuinely extended outage, which is why monitoring the duration of the disruption matters more than reacting to the first error event.
Duration and pattern. A deploy-related drop clears within a few seconds and correlates directly with your own deployment timeline — you can check whether one just happened. A real outage produces connection errors that persist well past that window, with no deploy to explain them, and is worth alerting on specifically once the disruption exceeds how long your deploys actually take.
Yes — an unhandled error event on an ioredis client can crash a Node process outright. Attaching an error event listener that logs the disruption rather than doing nothing is required regardless of how well-tuned your retryStrategy is, since even a correctly configured reconnect strategy still emits error events for each failed attempt along the way.
