Railway Integration
Using CAPYSQUASH with Railway PostgreSQL databases
RAILWAY INTEGRATION
Complete guide to using CAPYSQUASH with Railway PostgreSQL projects.
Railway provides instant PostgreSQL databases with zero configuration. CAPYSQUASH helps keep your migrations clean as your Railway project grows.
OVERVIEW
RAILWAY + CAPYSQUASH
Railway projects often start simple but migrations accumulate quickly. CAPYSQUASH keeps your database migrations organized.
Benefits:
- Clean up migration directories
- Faster Railway deployments
- Maintain migration history
- Safe consolidation with validation
- Works with Railway's auto-migrations
SETUP
Prerequisites
☑ RAILWAY CLI
Optional but recommended
☑ pgsquash-engine
Installed globally
☑ POSTGRESQL 14+
On Railway
Installation
# Install Railway CLI
npm install -g @railway/cli
# Install capysquash-cli
brew install capysquash-cli
# or
go install github.com/CAPYSQUASH/capysquash-cli/cmd/capysquash@latest
# Login to Railway
railway loginQUICK START
Step 1: Connect to Your Railway Project
# Link to Railway project
railway link
# Get database connection string
railway variablesYour Railway project should have:
- PostgreSQL database service
- Application service
- Migration files in your repository
Step 2: Locate Your Migrations
Common Railway migration locations:
# Prisma migrations
prisma/migrations/
# Drizzle migrations
drizzle/migrations/
# Custom migrations
db/migrations/
migrations/Step 3: Analyze
# Analyze your migrations
capysquash analyze migrations/*.sql
# Or for Prisma
capysquash analyze prisma/migrations/**/*.sqlExample Output:
🔍 ANALYZING MIGRATIONS...
Found: 67 migration files
Can consolidate to: 12 files
Reduction: 82.1%
Database operations:
► Tables created: 15
► Indexes: 23
► Foreign keys: 18
► Triggers: 2
☑ Railway PostgreSQL 14 compatible
☑ No blocking operations detectedStep 4: Consolidate
# Standard consolidation
capysquash squash migrations/*.sql --output=migrations_clean/
# For Prisma
capysquash squash prisma/migrations/**/*.sql --output=prisma/migrations_clean/Step 5: Validate
# Validate against Railway database
capysquash validate migrations/ migrations_clean/
# Or test locally first
docker run -d --name railway-test -e POSTGRES_PASSWORD=test postgres:14
capysquash validate migrations/ migrations_clean/ --db=railway-testRAILWAY-SPECIFIC PATTERNS
Connection String Format
Railway provides connection strings in this format:
postgresql://postgres:password@containers-us-west-123.railway.app:5432/railwayUsing with CAPYSQUASH:
# Export connection string
export DATABASE_URL="postgresql://postgres:password@containers-us-west-123.railway.app:5432/railway"
# Run validation against Railway
capysquash validate migrations/ migrations_clean/ --db-url=$DATABASE_URLEnvironment Variables
Railway automatically sets these variables:
DATABASE_URL # Full connection string
PGHOST # Database host
PGPORT # Database port (5432)
PGUSER # Username (postgres)
PGPASSWORD # Generated password
PGDATABASE # Database name (railway)Private Networking
For Railway private networking:
# Use private host
postgresql://postgres:password@postgres.railway.internal:5432/railwayORM INTEGRATION
Prisma
Railway + Prisma + CAPYSQUASH workflow:
# 1. Generate Prisma migration
npx prisma migrate dev --name add_users
# 2. After several migrations, consolidate
capysquash squash prisma/migrations/**/*.sql --output=clean/
# 3. Validate
capysquash validate prisma/migrations/ clean/
# 4. Replace migrations
rm -rf prisma/migrations
mv clean/ prisma/migrations/
# 5. Deploy to Railway
railway upPrisma-specific considerations:
- Preserve
migration_lock.toml - Keep
_prisma_migrationstable - Maintain migration timestamps
- Test with
npx prisma migrate resolve
Drizzle
Railway + Drizzle + CAPYSQUASH workflow:
# 1. Generate Drizzle migration
npx drizzle-kit generate:pg
# 2. Consolidate periodically
capysquash squash drizzle/migrations/*.sql --output=clean/
# 3. Deploy to Railway
npx drizzle-kit push:pgTypeORM
// ormconfig.json
{
"type": "postgres",
"url": process.env.DATABASE_URL,
"migrations": ["migrations/*.ts"],
"cli": {
"migrationsDir": "migrations"
}
}Consolidation workflow:
# Generate migrations
npm run typeorm migration:generate -- -n AddUser
# After accumulation
capysquash squash migrations/*.sql --output=clean/
# Deploy
railway upCI/CD INTEGRATION
GitHub Actions with Railway
name: Deploy to Railway
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pgsquash
run: go install github.com/CAPYSQUASH/pgsquash-engine/cmd/pgsquash@latest
- name: Squash migrations
run: |
pgsquash squash migrations/*.sql \
--safety=conservative \
--output=migrations_clean/
- name: Validate
env:
DATABASE_URL: ${{ secrets.RAILWAY_DATABASE_URL }}
run: |
pgsquash validate migrations/ migrations_clean/ \
--db-url=$DATABASE_URL
- name: Deploy to Railway
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
npm install -g @railway/cli
railway upRailway Deployments
Railway automatically runs migrations on deploy:
# Railway detects and runs:
# - prisma migrate deploy
# - drizzle-kit push
# - Custom migration scripts
# With pgsquash, deployments are faster:
# Before: 50 migrations × 200ms = 10 seconds
# After: 8 migrations × 200ms = 1.6 secondsDEPLOYMENT WORKFLOW
Development
# 1. Work on feature
railway run npm run dev
# 2. Create migrations as needed
npx prisma migrate dev
# 3. Periodically consolidate locally
capysquash squash prisma/migrations/**/*.sql --output=clean/
# 4. Test locally
railway run npx prisma migrate deploy
# 5. Push to Railway
git push
railway upProduction
SAFE PRODUCTION WORKFLOW
CREATE BACKUP
Use Railway's backup feature or pg_dump
TEST ON STAGING
Deploy to Railway staging environment first
VALIDATE
Run capysquash validate against production
DEPLOY
Push to production Railway service
COMMON SCENARIOS
Scenario 1: Prisma Development Cleanup
Problem: 100+ Prisma migration files after 6 months of development
Solution:
# Analyze Prisma migrations
capysquash analyze prisma/migrations/**/*.sql
# Consolidate with standard safety
capysquash squash prisma/migrations/**/*.sql \
--safety=standard \
--output=prisma/migrations_clean/
# Validate
capysquash validate \
prisma/migrations/ \
prisma/migrations_clean/
# Replace
rm -rf prisma/migrations
mv prisma/migrations_clean/ prisma/migrations/
# Test locally
npx prisma migrate resolve --applied "all"
npx prisma generate
# Deploy to Railway
railway upScenario 2: Monorepo with Multiple Services
Problem: Multiple Railway services sharing migrations
my-monorepo/
├── apps/
│ ├── api/ (Railway service)
│ ├── web/ (Railway service)
└── packages/
└── database/
└── migrations/ (shared)Solution:
# Consolidate shared migrations
cd packages/database
capysquash squash migrations/*.sql --output=clean/
# Validate against Railway database
export DATABASE_URL="$(railway variables get DATABASE_URL)"
capysquash validate migrations/ clean/ --db-url=$DATABASE_URL
# Update and deploy
mv clean/ migrations/
railway up --service api
railway up --service webScenario 3: Migration Performance Issues
Problem: Railway deployments slow due to many migrations
Before consolidation:
# Deployment logs:
Running 147 migrations... (8.2 seconds)After consolidation:
# Squash migrations
capysquash squash migrations/*.sql --output=clean/
# New deployment:
Running 15 migrations... (1.1 seconds)
# 86.6% faster! 🚀TROUBLESHOOTING
Connection Issues
Error:
connection refused: railway.app:5432Solution:
# Ensure DATABASE_URL is set
railway variables
# Test connection
railway run psql $DATABASE_URL -c "SELECT version();"
# Check Railway service status
railway statusMigration Conflicts
Error:
migration "xyz" already appliedSolution:
# Clear migration history (CAUTION)
railway run psql $DATABASE_URL -c "TRUNCATE _prisma_migrations;"
# Re-apply migrations
railway run npx prisma migrate deployValidation Failures
Error:
Schema mismatch detectedSolution:
# Use conservative safety
capysquash squash migrations/*.sql \
--safety=conservative \
--output=clean/
# Or paranoid for production
capysquash squash migrations/*.sql \
--safety=paranoid \
--output=clean/BEST PRACTICES
☑ RECOMMENDED
- Squash migrations monthly
- Use Railway's backup feature
- Test on staging environment
- Validate before production deploy
- Monitor Railway metrics after deploy
- Keep original migrations in git history
✗ AVOID
- Squashing deployed migrations
- Skipping validation step
- Using aggressive safety on production
- Deploying without testing
- Deleting migration backups
- Consolidating during high traffic
RAILWAY-SPECIFIC TIPS
Database Backups
# Manual backup before consolidation
railway run pg_dump $DATABASE_URL > backup.sql
# Or use Railway's backup feature
railway db backup create --service postgresMonitoring
# Check deployment logs
railway logs
# Monitor database performance
railway metrics --service postgres
# View recent queries
railway run psql $DATABASE_URL -c "SELECT * FROM pg_stat_activity;"Scaling Considerations
Before scaling Railway Postgres:
- Consolidate migrations first
- Fewer migrations = faster cold starts
- Better for horizontal scaling
- Improved deployment reliability
INTEGRATION WITH RAILWAY FEATURES
Railway Templates
Include CAPYSQUASH in your Railway template:
{
"name": "Next.js + PostgreSQL + capysquash",
"services": [
{
"name": "postgres",
"image": "postgres:14"
},
{
"name": "app",
"buildCommand": "npm run build",
"startCommand": "npm start",
"envVars": {
"DATABASE_URL": "${{postgres.DATABASE_URL}}"
}
}
],
"hooks": {
"postDeploy": "capysquash validate migrations/ --db-url=$DATABASE_URL"
}
}Railway Webhooks
Trigger migration consolidation via Railway webhooks:
// webhook-handler.js
app.post('/railway-webhook', async (req, res) => {
if (req.body.event === 'deployment.success') {
// Run consolidation after successful deployment
execSync('capysquash squash migrations/*.sql --output=clean/');
// Commit and push if needed
}
});PERFORMANCE BENCHMARKS
Railway Deployment Performance
Test project: Next.js + Prisma + PostgreSQL on Railway
| Metric | Before Squash | After Squash | Improvement |
|---|---|---|---|
| Migration count | 156 files | 18 files | 88.5% reduction |
| Deployment time | 42 seconds | 12 seconds | 71.4% faster |
| Cold start time | 8.2 seconds | 2.1 seconds | 74.4% faster |
| Repo size | 4.2 MB | 0.8 MB | 81% smaller |
NEXT STEPS
- Prisma Integration - Detailed Prisma guide
- Drizzle Integration - Drizzle-specific patterns
- TypeORM Guide - TypeORM integration
- Safety Levels - Choose the right safety
- CI/CD Integration - Advanced automation
How is this guide?