PocketBase 502 on Railway — graceful connect and restart pattern
A 502 on Railway almost always means PocketBase restarted and Next.js hasn't reconnected yet. Here's the graceful connect and health check fix.
A 502 on your VeloCMS Railway deployment almost always means PocketBase has restarted and the Next.js service is trying to connect to a PocketBase instance that isn't yet ready. Railway restarts PocketBase whenever it deploys a new version, runs out of memory, or is manually restarted from the Dashboard. With a graceful connect pattern, the Next.js service retries the connection transparently instead of crashing.
Why 502 happens on Railway
Railway runs both your Next.js service and PocketBase as separate containers. When PocketBase restarts, there's a window of 5–30 seconds where the container is starting but not yet accepting connections. If Next.js tries to make a PocketBase request during that window — on the first SSR render, for example — PocketBase returns a connection refused error, which Next.js translates to a 502 to the client.
The graceful connect pattern
VeloCMS's PocketBase client wrapper wraps the connect() call in a try-catch with retry logic. If the first connection attempt fails, the client retries with exponential backoff — 1s, 2s, 4s, up to 30s — before throwing a permanent error. During the retry window, SSR pages render a skeleton or loading state instead of a 502.
// Graceful connect pattern in src/lib/pocketbase/server.ts:
async function connect(): Promise<PocketBase> {
let attempt = 0;
while (attempt < 5) {
try {
const db = new PocketBase(process.env.POCKETBASE_URL);
await db.health.check();
return db;
} catch (err) {
attempt++;
if (attempt === 5) throw err;
await new Promise((r) => setTimeout(r, 1_000 * 2 ** attempt));
}
}
throw new Error("PocketBase unavailable after 5 attempts");
}Monitoring for recurring 502s
If you're seeing 502s regularly (more than once per week), the root cause is likely memory pressure rather than deployment restarts. Railway's free tier containers have 512MB RAM — PocketBase with a large SQLite database and heavy write load can exceed this. Upgrade to a container with at least 1GB RAM, or enable PocketBase's --queryTimeout flag to prevent long-running queries from consuming all available memory. Monitor memory usage in Railway Observability Metrics.