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 Command | PMDaemon Command | Status | 
|---|---|---|
pm2 start app.js | pmdaemon start app.js | ✅ Compatible | 
pm2 stop app | pmdaemon stop app | ✅ Compatible | 
pm2 restart app | pmdaemon restart app | ✅ Compatible | 
pm2 reload app | pmdaemon reload app | ✅ Compatible | 
pm2 delete app | pmdaemon delete app | ✅ Enhanced | 
pm2 list | pmdaemon list | ✅ Enhanced | 
pm2 monit | pmdaemon monit | ✅ Enhanced | 
pm2 logs app | pmdaemon logs app | ✅ Enhanced | 
pm2 describe app | pmdaemon 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
- 
Script field: PMDaemon separates the executable from arguments
- PM2: 
"script": "server.js" - PMDaemon: 
"script": "node", "args": ["server.js"] 
 - PM2: 
 - 
Environment configs: PMDaemon uses separate files for different environments
- PM2: 
env_productionin same file - PMDaemon: Separate 
production.json,development.jsonfiles 
 - PM2: 
 - 
Port configuration: PMDaemon uses strings for advanced port features
- PM2: 
"port": 3000 - PMDaemon: 
"port": "3000"or"port": "3000-3003" 
 - PM2: 
 
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
| Feature | PMDaemon | PM2 | Description | 
|---|---|---|---|
| Port Range Distribution | ✅ | ❌ | --port 3000-3003 distributes consecutive ports | 
| Auto Port Assignment | ✅ | ❌ | --port auto:5000-5100 finds available ports | 
| Runtime Port Override | ✅ | ❌ | Change ports during restart without config changes | 
| HTTP Health Checks | ✅ | ❌ | Monitor endpoints with configurable timeouts | 
| Script Health Checks | ✅ | ❌ | Custom health validation scripts | 
| Blocking Start | ✅ | ❌ | Wait for processes to be ready (--wait-ready) | 
| Bulk Delete Operations | ✅ | ❌ | delete all, delete stopped --status | 
| Configurable Monitor Intervals | ✅ | ❌ | monit --interval 5 for custom refresh rates | 
| Real-time Log Following | ✅ | ❌ | logs --follow with proper tail -f behavior | 
| Professional Table Display | ✅ | ❌ | Color-coded status, PID column, beautiful formatting | 
| WebSocket Real-time Updates | ✅ | ❌ | Live process status via WebSocket | 
What's Different
| Feature | PM2 | PMDaemon | Notes | 
|---|---|---|---|
| Ecosystem Files | JavaScript | JSON/YAML/TOML | PMDaemon supports multiple formats | 
| Environment Configs | Single file | Separate files | Use different files for dev/prod | 
| Port Configuration | Numbers | Strings | PMDaemon: "3000", "3000-3003", "auto:5000-5100" | 
| Memory Limits | Various formats | Standardized | PMDaemon: "512M", "1G", "100K" | 
| Log Management | Built-in rotation | External tools | Use 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 
pm2commands withpmdaemon -  Configure monitoring: Set up 
pmdaemon monitor 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
- Troubleshooting Guide - Common issues and solutions
 - GitHub Issues - Report migration problems
 - Examples - See real-world migration examples
 
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.