Skip to main content

Staging Environment Setup Runbook

Overview

Agentix deploys as two services: web (Next.js on Vercel) and api (Express + BullMQ on Railway). A staging environment mirrors production with separate infrastructure so that changes can be verified before they reach real users. Staging uses:
  • Railway — separate PostgreSQL, Redis, and API services (never shared with production)
  • Vercel — preview deployment on a dedicated staging branch
Why staging exists: Every database migration, feature flag, API change, and UI update should be validated in a production-like environment before deploying to production. Staging catches issues that local development and CI cannot: environment variable mismatches, migration ordering problems, and integration failures between services. Environment variables:
  • DATABASE_URL — staging PostgreSQL connection string
  • REDIS_URL — staging Redis connection string
  • All other API and web env vars with staging-specific values

1. Railway Staging Setup

Railway supports multiple environments within a single project. Each environment gets its own set of services and variables.
  1. Install the Railway CLI (if not already installed):
    npm install -g @railway/cli
    railway login
    
  2. Link to the Agentix project:
    railway link
    
  3. Create a staging environment:
    railway environment create staging
    
    This creates a parallel environment with its own services and variables, isolated from production.
  4. Switch to the staging environment:
    railway environment staging
    
  5. Provision a new PostgreSQL service for staging:
    • Railway Dashboard > Project > switch to staging environment (top-left dropdown).
    • Click New > Database > PostgreSQL.
    • Railway auto-generates DATABASE_URL for this service.
  6. Provision a new Redis service for staging:
    • In the staging environment, click New > Database > Redis.
    • Railway auto-generates REDIS_URL for this service.
  7. Deploy the API to staging:
    • Railway auto-deploys the API service in the staging environment using the same Dockerfile and railway.toml configuration.
    • Push to the branch configured for staging (e.g., staging), or trigger a manual deploy:
      railway environment staging
      railway up
      

Option B: Separate Railway Services (Alternative)

If Railway environments are not available on your plan:
  1. In the same Railway project, create new services manually:
    • staging-api — deploy from the same repo/Dockerfile
    • staging-postgres — new PostgreSQL service
    • staging-redis — new Redis service
  2. Configure each service’s variables independently (see Section 2).
  3. Set the staging API service to deploy from a staging branch:
    • Railway Dashboard > staging-api service > Settings > Source > set branch to staging.

Dashboard Navigation (Both Options)

  1. Open the Railway Dashboard.
  2. Select the Agentix project.
  3. Use the environment dropdown (top-left) to switch between production and staging.
  4. Each environment shows its own services, variables, and deployment logs.

2. Staging Environment Variables

WARNING: Never copy the production DATABASE_URL or REDIS_URL to staging. Staging must use its own isolated database and Redis instances. Using production credentials in staging risks data corruption or accidental data deletion.

API Environment Variables (apps/api)

Set these in Railway for the staging API service:
VariableStaging ValueNotes
PORT3001Railway assigns automatically; usually not needed
DATABASE_URLpostgresql://... (staging PostgreSQL)Auto-generated by Railway staging PostgreSQL service
REDIS_URLredis://... (staging Redis)Auto-generated by Railway staging Redis service
FRONTEND_URLhttps://agentix-app-staging.vercel.appStaging Vercel preview URL (see Section 3)
BETTER_AUTH_SECRETGenerate a new secret: openssl rand -hex 32Must be different from production — shared secrets leak sessions between environments
OPENAI_API_KEYsk-...Can share with production or use a separate test key with lower limits
CREDENTIAL_ENCRYPTION_KEYGenerate a new key: openssl rand -hex 32Must be different from production — sharing this key means staging can decrypt production credentials
RESEND_API_KEYre_...Can share with production — WARNING: staging emails go to real email addresses. Use test mode or a separate Resend domain to avoid sending real emails during testing
FROM_EMAILAgentix Staging <noreply@mail.agentix.app>Add “Staging” prefix so recipients know the email source
SENTRY_DSNSame DSN as production OR separate staging projectIf sharing: set SENTRY_ENVIRONMENT=staging so errors are tagged. If separate: create a new Sentry project for staging
POSTHOG_API_KEYSame as productionFilter by environment in PostHog dashboard
POSTHOG_HOSThttps://us.i.posthog.comSame as production

Web Environment Variables (apps/web)

Set these in Vercel for the staging/preview environment:
VariableStaging ValueNotes
NEXT_PUBLIC_API_URLhttps://staging-api.up.railway.appMust point to staging Railway API, not production
NEXT_PUBLIC_SENTRY_DSNSame DSN or staging-specificMatch API Sentry strategy
SENTRY_ORGagentixSame as production
SENTRY_PROJECTagentix-webSame as production (or agentix-web-staging if separate)
SENTRY_AUTH_TOKENsntrys_...Can share with production
NEXT_PUBLIC_POSTHOG_KEYSame as productionFilter by environment in PostHog
NEXT_PUBLIC_POSTHOG_HOSThttps://us.i.posthog.comSame as production

Generating Secrets

# Generate BETTER_AUTH_SECRET for staging
openssl rand -hex 32

# Generate CREDENTIAL_ENCRYPTION_KEY for staging
openssl rand -hex 32
Never reuse production secrets. Each environment must have its own authentication and encryption keys.

3. Vercel Staging / Preview

Vercel automatically creates preview deployments for every push to a non-production branch. To create a dedicated staging environment:

Configure a Staging Branch

  1. Open the Vercel Dashboard.
  2. Select the Agentix web project.
  3. Go to Settings > Git.
  4. Under Production Branch, confirm it is set to main.
  5. Create a staging branch in Git:
    git checkout -b staging
    git push -u origin staging
    
  6. Vercel will automatically create a preview deployment for the staging branch.

Set Staging-Specific Environment Variables

  1. In Vercel, go to Project Settings > Environment Variables.
  2. For each variable, select the Preview environment (not Production).
  3. Set NEXT_PUBLIC_API_URL to the staging Railway API URL:
    NEXT_PUBLIC_API_URL = https://staging-api.up.railway.app
    
  4. Set other staging-specific values (Sentry, PostHog) as needed.
Important: Vercel environment variables are scoped by environment. Variables set for “Preview” only apply to preview deployments (including the staging branch). Variables set for “Production” only apply to the main branch deployment.

Accessing the Staging Preview URL

  • Branch URL: https://agentix-app-git-staging-<team>.vercel.app
  • Deployment URL: Each deployment gets a unique URL visible in the Vercel dashboard > Deployments tab.
  • Alias (optional): Configure a custom domain like staging.agentix.app in Vercel Domains settings for a stable URL.

4. Database Schema Sync

After provisioning the staging PostgreSQL instance, apply all Prisma migrations to create the schema.

Apply Migrations

# Set the staging DATABASE_URL
export STAGING_DATABASE_URL="postgresql://..."  # from Railway staging PostgreSQL service

# Run all pending migrations
DATABASE_URL="$STAGING_DATABASE_URL" npx prisma migrate deploy
prisma migrate deploy applies all pending migrations in order. It is safe to run multiple times (idempotent — skips already-applied migrations).

Verify Migration Status

DATABASE_URL="$STAGING_DATABASE_URL" npx prisma migrate status
Expected output: Database schema is up to date!

Seed Test Data (Optional)

For testing, you may want seed data in the staging database: Option A: Prisma Studio (manual)
DATABASE_URL="$STAGING_DATABASE_URL" npx prisma studio
Opens a web UI where you can manually create tenants, users, and test data. Option B: Seed script (automated)
DATABASE_URL="$STAGING_DATABASE_URL" npx prisma db seed
Requires a prisma/seed.ts file to be configured in the API project. Option C: Copy structure from production (no data) If you need realistic schema but not production data, the migrations alone create the full schema. Add test data manually via Prisma Studio or API requests.

5. Verification Checklist

After setting up the staging environment, verify each component:
  • Staging API health check passes:
    curl https://staging-api.up.railway.app/health
    
    Expected: {"status":"ok","timestamp":"...","checks":{"db":"ok","redis":"ok"}}
  • Staging web loads at preview URL: Open https://agentix-app-git-staging-<team>.vercel.app in a browser. Confirm the login page renders.
  • Staging web connects to staging API (not production): Open browser DevTools > Network tab. Verify API requests go to the staging Railway URL, not the production URL.
  • Database has schema (no pending migrations):
    DATABASE_URL="$STAGING_DATABASE_URL" npx prisma migrate status
    
    Expected: Database schema is up to date!
  • Redis is reachable:
    redis-cli -u "$STAGING_REDIS_URL" PING
    
    Expected: PONG Or check via the health endpoint — the redis: ok check confirms connectivity.
  • Test webhook can be sent to staging webhook URL:
    curl -X POST https://staging-api.up.railway.app/webhooks/whatsapp \
      -H "Content-Type: application/json" \
      -d '{"object":"whatsapp_business_account","entry":[]}'
    
    Should return a 200 response (empty entry array is safely handled).
  • Sentry errors from staging are tagged with staging environment: Trigger a deliberate error and confirm it appears in Sentry with the staging environment tag.

6. Maintenance

Keep Schema in Sync

Always run migrations on staging before production. This validates that migrations apply cleanly on a production-like database.
# Before every production deploy that includes migrations:
DATABASE_URL="$STAGING_DATABASE_URL" npx prisma migrate deploy

# Verify staging works, then deploy to production
DATABASE_URL="$PRODUCTION_DATABASE_URL" npx prisma migrate deploy

Periodic Data Cleanup

Staging databases accumulate test data over time. Periodically truncate or reset:
# Option A: Reset staging database (drops all data, re-applies migrations)
DATABASE_URL="$STAGING_DATABASE_URL" npx prisma migrate reset --force

# Option B: Selective cleanup via Prisma Studio
DATABASE_URL="$STAGING_DATABASE_URL" npx prisma studio
WARNING: Never run prisma migrate reset against production. The --force flag skips confirmation — use with caution.

Cost Considerations

Railway staging services incur separate charges:
ServiceApproximate Monthly Cost
PostgreSQL (staging)$5-10/month (Pro plan)
Redis (staging)$5-10/month (Pro plan)
API service (staging)$5-10/month (varies by usage)
To reduce costs during inactive periods, you can pause or delete staging services via the Railway dashboard and recreate them when needed.

Railway CLI Quick Reference

# Switch to staging environment
railway environment staging

# View staging service logs
railway logs

# Open staging database in Railway shell
railway connect postgres

# Trigger a manual deploy
railway up

# View staging variables
railway variables