CAPYSQUASH

---

CAPYSQUASH documentation page.

---

Title: Railway Integration. Description: 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

    </div>

    ### Step 4: Consolidate

    ```bash

- # Standard consolidation

- capysquash squash migrations/\*.sql --output=migrations_clean/

- # For Prisma

- capysquash squash prisma/migrations/\*\*/\*.sql --output=prisma/migrations_clean/

### Step 5: Validate

```bash

# 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

| 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

How is this guide?

On this page