Deployment Debugging: Railway & Vercel
Debugging deployment issues on Railway and Vercel platforms.
When to Use
- •Build failures on Railway or Vercel
- •Environment variable issues
- •Cold start problems
- •Runtime errors in production
- •Deployment configuration issues
Railway Debugging
Build Failures
Symptom: Build hangs or times out
Check:
bash
# Railway build logs railway logs --build # Common causes: # 1. No Dockerfile or nixpacks.toml # 2. Large dependencies being installed # 3. Memory limits exceeded
Solution - Add railway.toml:
toml
[build] builder = "nixpacks" buildCommand = "cargo build --release" [deploy] startCommand = "cargo run --release" healthcheckPath = "/health" healthcheckTimeout = 300
Symptom: Cargo/Rust build fails
Common issues:
bash
# Missing system dependencies # Add to nixpacks.toml: [phases.setup] aptPkgs = ["libssl-dev", "pkg-config"] # Or use Dockerfile FROM rust:1.75 as builder RUN apt-get update && apt-get install -y libssl-dev pkg-config
Symptom: Node.js build fails
bash
# Check Node version
# Add to package.json:
{
"engines": {
"node": ">=20"
}
}
# Or railway.toml:
[build]
nixpacksConfigPath = "nixpacks.toml"
Environment Variables
Symptom: Env vars not available at build time
Solution: Use Railway's variable references:
bash
# In Railway dashboard, use references:
DATABASE_URL=${{Postgres.DATABASE_URL}}
# Or for secrets:
API_KEY=${{secrets.API_KEY}}
Symptom: Env vars not in runtime
Check:
rust
// Debug endpoint
#[get("/debug/env")]
fn debug_env() -> String {
std::env::vars()
.filter(|(k, _)| !k.contains("SECRET") && !k.contains("KEY"))
.map(|(k, v)| format!("{}: {}", k, v))
.collect::<Vec<_>>()
.join("\n")
}
Networking
Symptom: Can't connect to database
Check Railway's internal networking:
bash
# Use internal hostname for Railway services DATABASE_URL=postgres://user:pass@postgres.railway.internal:5432/db # Not the public URL for internal services
Symptom: Port issues
bash
# Railway sets PORT automatically
# Use it in your code:
let port = std::env::var("PORT").unwrap_or("3000".to_string());
Health Checks
toml
# railway.toml [deploy] healthcheckPath = "/health" healthcheckTimeout = 300 restartPolicyType = "ON_FAILURE" restartPolicyMaxRetries = 3
rust
// Implement health endpoint
#[get("/health")]
fn health() -> &'static str {
"OK"
}
Vercel Debugging
Build Failures
Symptom: Next.js build fails
bash
# Check Vercel build logs
vercel logs <deployment-url>
# Common fixes in next.config.js:
module.exports = {
eslint: {
ignoreDuringBuilds: true, // If ESLint issues blocking
},
typescript: {
ignoreBuildErrors: true, // Last resort for TS errors
},
};
Symptom: "Module not found" in build
bash
# Ensure dependencies in dependencies, not devDependencies
# Or configure for build:
{
"vercel": {
"installCommand": "bun install --production=false"
}
}
Environment Variables
Symptom: Env vars undefined in client
Root cause: Only NEXT_PUBLIC_* vars are exposed to client.
typescript
// Server-side only const apiKey = process.env.API_KEY; // Works in server components/API routes // Client-side const publicKey = process.env.NEXT_PUBLIC_KEY; // Must have NEXT_PUBLIC_ prefix
Symptom: Env vars not in serverless functions
Check Vercel dashboard Environment Variables:
- •Production vs Preview vs Development
- •Scope to specific branches if needed
Serverless Function Issues
Symptom: Function timeout
typescript
// vercel.json - increase timeout (Pro/Enterprise only)
{
"functions": {
"app/api/**/*.ts": {
"maxDuration": 60
}
}
}
// For Hobby plan, optimize function:
export const maxDuration = 10; // seconds
Symptom: Cold starts slow
Solutions:
- •Use Edge Runtime for simple functions:
typescript
export const runtime = 'edge';
- •Keep functions warm (Pro feature):
json
{
"crons": [{
"path": "/api/health",
"schedule": "*/5 * * * *"
}]
}
- •Reduce bundle size:
typescript
// Only import what you need
import { specificFunction } from 'large-library/specific';
Symptom: 500 errors in production only
Debug locally with production env:
bash
vercel env pull .env.local vercel dev
Check function logs:
bash
vercel logs <deployment-url> --follow
Edge Functions
Symptom: API not available in Edge
Root cause: Node.js APIs not available in Edge Runtime.
typescript
// Bad - uses Node.js
import { readFile } from 'fs';
// Good - Edge compatible
export const runtime = 'edge';
export async function GET() {
// Use fetch, not fs
const data = await fetch('...');
}
Caching Issues
Symptom: Stale data after deploy
typescript
// Disable caching for dynamic data
export const dynamic = 'force-dynamic';
export const revalidate = 0;
// Or use cache tags
import { revalidateTag } from 'next/cache';
revalidateTag('posts');
General Debugging
Structured Logging
typescript
// Add correlation IDs
export async function middleware(request: NextRequest) {
const requestId = crypto.randomUUID();
console.log(JSON.stringify({
requestId,
path: request.nextUrl.pathname,
method: request.method,
timestamp: new Date().toISOString(),
}));
}
Error Boundaries
typescript
// app/error.tsx
'use client';
export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
console.error('App error:', error);
return (
<div>
<h2>Something went wrong</h2>
<button onClick={reset}>Try again</button>
</div>
);
}
Local Production Testing
bash
# Next.js bun run build && bun run start # Railway railway run -- cargo run --release # Vercel vercel build && vercel dev
Quick Checklist
Before Deploying
- • All env vars set in platform dashboard
- • Build command correct
- • Start command correct
- • Health check endpoint exists
- • Production dependencies complete
After Failed Deploy
- •Check build logs first
- •Verify environment variables
- •Test locally with production env
- •Check for platform-specific limitations
- •Review recent changes