pm2 and Environments

Running on a VM with pm2

On a plain Linux VM (GCP, AWS EC2, DigitalOcean), pm2 keeps the app running, restarts it on crash and can run one process per CPU core.

ecosystem.config.js

module.exports = {
  apps: [
    {
      name: 'shopease-api',
      script: 'dist/main.js',
      instances: 'max',            // one per CPU core
      exec_mode: 'cluster',
      max_memory_restart: '512M',
      env_production: { NODE_ENV: 'production', PORT: 3000 },
      env_staging: { NODE_ENV: 'production', PORT: 3100 },
    },
  ],
};

Example

npm ci && npm run build && npx prisma migrate deploy
pm2 start ecosystem.config.js --env production
pm2 status

Example output

[PM2] Starting /srv/shopease-api/dist/main.js in cluster_mode (4 instances)
[PM2] Done.
┌────┬────────────────┬─────────┬──────┬────────┬────────┬──────────┐
│ id │ name           │ mode    │ ↺    │ status │ cpu    │ memory   │
├────┼────────────────┼─────────┼──────┼────────┼────────┼──────────┤
│ 0  │ shopease-api   │ cluster │ 0    │ online │ 0%     │ 92.4mb   │
│ 1  │ shopease-api   │ cluster │ 0    │ online │ 0%     │ 90.1mb   │
│ 2  │ shopease-api   │ cluster │ 0    │ online │ 0%     │ 91.7mb   │
│ 3  │ shopease-api   │ cluster │ 0    │ online │ 0%     │ 89.8mb   │
└────┴────────────────┴─────────┴──────┴────────┴────────┴──────────┘

Tip: Use pm2 reload shopease-api for zero-downtime deploys (instances restart one by one), and put nginx in front for HTTPS and gzip.

One Build, Many Environments

SettingDevelopmentStagingProduction
Source of config.env.localCI secretsSecret manager
DatabaseDocker on laptopSmall managed DBManaged DB with backups and replicas
LogsPretty text, debugJSON, debugJSON, info
Swagger /docsOnOnOff or behind auth
CORS originslocalhoststaging domainshopease.in only