Skip to main content

Migration from PM2

Migrating from PM2 to PMDaemon is straightforward thanks to PMDaemon's PM2-compatible command interface. This guide helps you transition smoothly while taking advantage of PMDaemon's enhanced features.

Command Compatibility

PMDaemon provides a PM2-compatible CLI, so most of your existing commands work unchanged:

Direct Command Mapping

PM2 CommandPMDaemon CommandStatus
pm2 start app.jspmdaemon start app.js✅ Compatible
pm2 stop apppmdaemon stop app✅ Compatible
pm2 restart apppmdaemon restart app✅ Compatible
pm2 reload apppmdaemon reload app✅ Compatible
pm2 delete apppmdaemon delete app✅ Enhanced
pm2 listpmdaemon list✅ Enhanced
pm2 monitpmdaemon monit✅ Enhanced
pm2 logs apppmdaemon logs app✅ Enhanced
pm2 describe apppmdaemon info app✅ Compatible

Enhanced Commands

PMDaemon extends PM2 commands with additional features:

# PM2 style (works in PMDaemon)
pmdaemon start app.js --name myapp --instances 4

# PMDaemon enhancements
pmdaemon start app.js --name myapp --instances 4 \
--port 3000-3003 \ # Port range distribution
--health-check-url http://localhost:3000/health \ # Health checks
--wait-ready # Blocking start

Configuration Migration

PM2 Ecosystem Files

PM2 ecosystem.config.js:

module.exports = {
apps: [{
name: 'my-app',
script: 'server.js',
instances: 4,
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
};

PMDaemon ecosystem.json:

{
"apps": [{
"name": "my-app",
"script": "node",
"args": ["server.js"],
"instances": 4,
"env": {
"NODE_ENV": "production"
}
}]
}

Key Differences

  1. Script field: PMDaemon separates the executable from arguments

    • PM2: "script": "server.js"
    • PMDaemon: "script": "node", "args": ["server.js"]
  2. Environment configs: PMDaemon uses separate files for different environments

    • PM2: env_production in same file
    • PMDaemon: Separate production.json, development.json files
  3. Port configuration: PMDaemon uses strings for advanced port features

    • PM2: "port": 3000
    • PMDaemon: "port": "3000" or "port": "3000-3003"

Migration Steps

Step 1: Install PMDaemon

cargo install pmdaemon

Step 2: Stop PM2 Processes

# List current PM2 processes
pm2 list

# Stop all PM2 processes
pm2 stop all

# Save PM2 configuration for reference
pm2 save

Step 3: Convert Configuration

Use this script to convert PM2 ecosystem files:

#!/bin/bash
# convert-pm2-config.sh

# Check if ecosystem.config.js exists
if [ ! -f "./ecosystem.config.js" ]; then
echo "Error: ecosystem.config.js not found in current directory"
exit 1
fi

# Convert PM2 ecosystem.config.js to PMDaemon ecosystem.json
node -e "
try {
const pm2Config = require('./ecosystem.config.js');
if (!pm2Config.apps || !Array.isArray(pm2Config.apps)) {
throw new Error('Invalid ecosystem.config.js: apps array not found');
}
const pmdConfig = {
apps: pm2Config.apps.map(app => ({
name: app.name,
script: app.interpreter || 'node',
args: [app.script, ...(app.args || [])],
instances: app.instances || 1,
port: app.env?.PORT ? String(app.env.PORT) : undefined,
max_memory_restart: app.max_memory_restart,
cwd: app.cwd,
env: app.env_production || app.env || {},
autorestart: app.autorestart !== false,
max_restarts: app.max_restarts || 16
}))
};
console.log(JSON.stringify(pmdConfig, null, 2));
} catch (error) {
console.error('Conversion failed:', error.message);
process.exit(1);
}
" > ecosystem.json

### Step 4: Start with PMDaemon

```bash
# Start all apps from converted config
pmdaemon --config ecosystem.json start

# Or start individual processes
pmdaemon start "node server.js" --name my-app --instances 4

Step 5: Verify Migration

# Check processes are running
pmdaemon list

# Compare with PM2 output
pm2 list

Feature Comparison

What PMDaemon Has That PM2 Doesn't

FeaturePMDaemonPM2Description
Port Range Distribution--port 3000-3003 distributes consecutive ports
Auto Port Assignment--port auto:5000-5100 finds available ports
Runtime Port OverrideChange ports during restart without config changes
HTTP Health ChecksMonitor endpoints with configurable timeouts
Script Health ChecksCustom health validation scripts
Blocking StartWait for processes to be ready (--wait-ready)
Bulk Delete Operationsdelete all, delete stopped --status
Configurable Monitor Intervalsmonit --interval 5 for custom refresh rates
Real-time Log Followinglogs --follow with proper tail -f behavior
Professional Table DisplayColor-coded status, PID column, beautiful formatting
WebSocket Real-time UpdatesLive process status via WebSocket

What's Different

FeaturePM2PMDaemonNotes
Ecosystem FilesJavaScriptJSON/YAML/TOMLPMDaemon supports multiple formats
Environment ConfigsSingle fileSeparate filesUse different files for dev/prod
Port ConfigurationNumbersStringsPMDaemon: "3000", "3000-3003", "auto:5000-5100"
Memory LimitsVarious formatsStandardizedPMDaemon: "512M", "1G", "100K"
Log ManagementBuilt-in rotationExternal toolsUse logrotate or similar

Common Migration Issues

1. Port Configuration

Problem: PM2 uses numbers, PMDaemon uses strings

// PM2
{ port: 3000 }

// PMDaemon
{ "port": "3000" }

Solution: Convert port numbers to strings in your config files.

2. Script vs Command

Problem: PM2 combines script and interpreter

// PM2
{ script: "server.js" }

// PMDaemon
{ "script": "node", "args": ["server.js"] }

Solution: Separate the interpreter from the script file.

3. Environment-specific Configs

Problem: PM2 supports env_production in same file

// PM2
{
env: { NODE_ENV: 'development' },
env_production: { NODE_ENV: 'production' }
}

Solution: Create separate config files:

# development.json
{ "apps": [{ "env": { "NODE_ENV": "development" } }] }

# production.json
{ "apps": [{ "env": { "NODE_ENV": "production" } }] }

4. Memory Format

Problem: PM2 accepts various memory formats

// PM2 (various formats)
{ max_memory_restart: "1024M" }
{ max_memory_restart: "1G" }

Solution: Use PMDaemon's standardized format:

{ "max_memory_restart": "1G" }

Migration Checklist

  • Install PMDaemon: cargo install pmdaemon
  • Backup PM2 config: pm2 save
  • Stop PM2 processes: pm2 stop all
  • Convert ecosystem files: Use conversion script or manual conversion
  • Update port configurations: Change numbers to strings
  • Separate environment configs: Create dev/prod specific files
  • Test PMDaemon startup: pmdaemon --config ecosystem.json start
  • Verify process status: pmdaemon list
  • Test health checks: Add health check configurations
  • Update deployment scripts: Replace pm2 commands with pmdaemon
  • Configure monitoring: Set up pmdaemon monit or web API
  • Update documentation: Update team docs with new commands

Taking Advantage of New Features

Once migrated, enhance your setup with PMDaemon's unique features:

1. Add Port Management

# Before (PM2)
pm2 start server.js --instances 4

# After (PMDaemon with port ranges)
pmdaemon start server.js --instances 4 --port 3000-3003

2. Add Health Checks

{
"apps": [{
"name": "api-server",
"script": "node",
"args": ["server.js"],
"health_check": {
"check_type": "http",
"url": "http://localhost:3000/health",
"timeout": 5,
"interval": 30,
"retries": 3
}
}]
}

3. Use Blocking Start in Deployment

# Wait for service to be ready before continuing
pmdaemon start server.js --health-check-url http://localhost:3000/health --wait-ready
echo "Service is ready for traffic!"

4. Enhanced Monitoring

# Real-time monitoring with custom intervals
pmdaemon monit --interval 2

# Follow logs in real-time
pmdaemon logs api-server --follow

Getting Help


Welcome to PMDaemon! 🎉 You now have access to advanced features that go beyond what PM2 offers, while maintaining the familiar interface you're used to.