The application was building successfully on Railway but failing during the health check phase with the error:
Healthcheck failed!
1/1 replicas never became healthy!
All 6 health check attempts to /api/health failed with "service unavailable".
Missing Database Migration Step: The deployment process was:
- ✅ Installing dependencies
- ✅ Generating Prisma client
- ✅ Building the Next.js application
- ❌ MISSING: Pushing database schema to PostgreSQL
- ❌ Starting the server (which tried to connect to an empty database)
When the application started, it tried to connect to the PostgreSQL database, but the database tables didn't exist because we never ran prisma db push or prisma migrate deploy. This caused the application to fail to start properly, resulting in health check failures.
File: package.json
Changed the start script to include database migration:
"start": "prisma db push --skip-generate --accept-data-loss && node .next/standalone/server.js"Why this works:
prisma db push --skip-generate: Pushes the schema to the database without regenerating the client (already done during build)--accept-data-loss: Required flag forprisma db pushin production (safe for initial deployments)&& node .next/standalone/server.js: Only starts the server if migration succeeds
The following files were already correctly configured:
railway.json:
{
"deploy": {
"startCommand": "npm start",
"healthcheckPath": "/api/health",
"healthcheckTimeout": 120
}
}nixpacks.toml:
[phases.install]
cmds = [
"npm ci --ignore-scripts",
"npm run db:generate" # Generates Prisma client
]
[phases.build]
cmds = [
"npm run build",
"cp -r public .next/standalone/public || true",
"cp -r .next/static .next/standalone/.next/static || true"
]
[start]
cmd = "npm start" # Now includes migration- Setup Phase: Install Node.js 20
- Install Phase:
- Run
npm ci --ignore-scripts(install dependencies) - Run
npm run db:generate(generate Prisma client)
- Run
- Build Phase:
- Run
npm run build(build Next.js app in standalone mode) - Copy public and static files to standalone output
- Run
- Start Phase (NEW BEHAVIOR):
- Run
prisma db push --skip-generate --accept-data-loss(create database tables) - Run
node .next/standalone/server.js(start the server)
- Run
- Health Check:
- Railway checks
/api/health - Should now return
200 OK✅
- Railway checks
- Ensure all environment variables are set in Railway dashboard:
DATABASE_URL(automatically set by Railway when PostgreSQL is added)NEXT_PUBLIC_REOWN_PROJECT_IDNEXT_PUBLIC_APP_URL(your Railway domain)NEXTAUTH_URL(same as above)NEXTAUTH_SECRET
-
Commit the changes:
git add package.json nixpacks.toml git commit -m "Fix: Add database migration to start command" git push origin main -
Railway will automatically redeploy
-
Monitor the deployment logs in Railway dashboard
You should see:
> neetmetree@0.1.0 start
> prisma db push --skip-generate --accept-data-loss && node .next/standalone/server.js
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "railway"
🚀 Your database is now in sync with your Prisma schema.
✔ Generated Prisma Client
[Server started successfully]
[Health check] Attempt #1 succeeded ✅
We considered but didn't use these approaches:
-
Using
prisma migrate deploy:- Requires migration files in
prisma/migrations/ - More complex setup, better for production with migration history
- Would require:
prisma migrate deploy && node .next/standalone/server.js
- Requires migration files in
-
Separate migration step in nixpacks.toml:
- Could add a
postBuildphase - Less straightforward than including in start command
- Could add a
-
Using Railway's Build Command:
- Could run migration as part of build
- Not ideal because build phase doesn't have access to production DATABASE_URL
The --accept-data-loss flag is safe in this scenario because:
- On first deployment: Creates all tables from scratch (no data to lose)
- On subsequent deployments: If schema hasn't changed, does nothing
- If schema changed: Updates tables (this is development-friendly)
For production applications with sensitive data, consider:
- Using
prisma migrate deploywith proper migration files - Setting up a CI/CD pipeline with migration verification
- Creating database backups before schema changes
- The standalone mode (
output: 'standalone'innext.config.js) is correctly configured - The health endpoint at
/pages/api/health.tsis working correctly - The issue was purely related to database initialization timing
After deployment succeeds, verify:
- ✅ Application is accessible at your Railway domain
- ✅ Health endpoint responds:
https://your-domain.railway.app/api/health - ✅ Database tables exist (check using Prisma Studio or Railway dashboard)
- ✅ Can create user accounts and links
Issue Resolved: Database migration now runs before server starts, ensuring all tables exist when the application initializes.