CAPYSQUASH

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 login

QUICK START

Step 1: Connect to Your Railway Project

# Link to Railway project
railway link

# Get database connection string
railway variables

Your 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/**/*.sql

Example 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 detected

Step 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-test

RAILWAY-SPECIFIC PATTERNS

Connection String Format

Railway provides connection strings in this format:

postgresql://postgres:password@containers-us-west-123.railway.app:5432/railway

Using 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_URL

Environment 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/railway

ORM 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 up

Prisma-specific considerations:

  • Preserve migration_lock.toml
  • Keep _prisma_migrations table
  • 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:pg

TypeORM

// 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 up

CI/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 up

Railway 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 seconds

DEPLOYMENT 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 up

Production

SAFE PRODUCTION WORKFLOW

1
CREATE BACKUP

Use Railway's backup feature or pg_dump

2
TEST ON STAGING

Deploy to Railway staging environment first

3
VALIDATE

Run capysquash validate against production

4
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 up

Scenario 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 web

Scenario 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:5432

Solution:

# Ensure DATABASE_URL is set
railway variables

# Test connection
railway run psql $DATABASE_URL -c "SELECT version();"

# Check Railway service status
railway status

Migration Conflicts

Error:

migration "xyz" already applied

Solution:

# Clear migration history (CAUTION)
railway run psql $DATABASE_URL -c "TRUNCATE _prisma_migrations;"

# Re-apply migrations
railway run npx prisma migrate deploy

Validation Failures

Error:

Schema mismatch detected

Solution:

# 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 postgres

Monitoring

# 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

MetricBefore SquashAfter SquashImprovement
Migration count156 files18 files88.5% reduction
Deployment time42 seconds12 seconds71.4% faster
Cold start time8.2 seconds2.1 seconds74.4% faster
Repo size4.2 MB0.8 MB81% smaller

NEXT STEPS

How is this guide?

On this page