3 min read

Manage Long-Running Processes with PM2

This article explains how to effectively manage a long-running Node.js price scraper with PM2, covering setup, monitoring, metrics, and deployment for continuous MongoDB updates.

Ever had a Node.js script that needs to run for hours, updating your database continuously? Let me show you how we handle this at our price comparison service.

Our system needs to constantly fetch prices from different suppliers and update MongoDB. It's a beast that runs 24/7, processing thousands of products. Here's how we tamed it with PM2.

You might be thinking "I'll just run it with node script.js and maybe add some nohup or screen session." Been there, done that. But then:

  • Your script crashes? You're not even aware until customers complain
  • Memory leak? Have fun SSH-ing at 3 AM to restart it
  • Need logs? Good luck digging through random .log files
  • Want metrics? "I'll just add console.log everywhere"
  • Multiple servers? Now you're juggling multiple SSH sessions

PM2 solves all of this. It's like having a professional DevOps team in a single command:

1. Basic Setup

First, install PM2 globally:

npm install -g pm2

Your price scraper (price-scraper.js):

async function main() {
  while(true) {
    console.log('Fetching new prices...');
    await updatePrices();
    await sleep(60000); // Wait 1 minute
  }
}

main().catch(console.error);

Your ecosystem.config.js:

module.exports = {
  apps: [{
    name: 'price-scraper',
    script: 'price-scraper.js',
    instances: 1,
    max_memory_restart: '1G',
    error_file: 'logs/error.log',
    out_file: 'logs/out.log',
    merge_logs: true,
    log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
    env: {
      NODE_ENV: 'production'
    }
  }]
}

2. Essential Commands

Start your app:

pm2 start ecosystem.config.js

Stop everything:

pm2 stop all

Stop specific app:

pm2 stop price-scraper

Restart:

pm2 restart price-scraper

Delete from PM2:

pm2 delete price-scraper

3. Real-time Monitoring

Terminal monitoring:

pm2 monit

View logs:

pm2 logs              # All logs
pm2 logs price-scraper # App specific
pm2 logs --lines 200  # Last 200 lines

Check status:

pm2 status
pm2 list             # Same as status

4. PM2 Plus (app.pm2.io) Integration

Now imagine you want to monitor your long-running application from anywhere. you can use the pm2 dashboard for this. In a nutshell, your pm2 sends the trace of the applications it manages to pm2.io. and you can see the current status at any time.

To use the PM2 Plus dashboard:

  1. Install PM2 Runtime on your server:
npm install -g pm2
  1. Link PM2 to PM2.io (get your link command after creating a bucket on app.pm2.io):
pm2 link xxxx  # Replace xxxx with your bucket's link command
  1. Start your application:
pm2 start ecosystem.config.js

Now you can add custom metrics to your app:

const io = require('@pm2/io')

// Counter metric
const pricesUpdated = io.counter({
  name: 'Prices Updated'
})

// Gauge for memory
const memoryUsage = io.metric({
  name: 'Memory Usage'
})

async function updatePrices() {
  pricesUpdated.inc()
  memoryUsage.set(process.memoryUsage().heapUsed)
  // ... rest of your code
}

Now on app.pm2.io you'll see:

  • Real-time metrics
  • CPU/Memory usage
  • Custom metrics you added
  • Exception tracking
  • Log management
  • Deployment history

5. Deployment Example

Save your deployment config:

pm2 save

Start on system boot:

pm2 startup

Deploy new version:

git pull
pm2 reload ecosystem.config.js

6. Health Checks

Add health endpoint to your app:

const http = require('http');

http.createServer((req, res) => {
  if (req.url === '/health') {
    res.writeHead(200);
    res.end('OK');
  }
}).listen(9209);

Monitor in ecosystem.config.js:

module.exports = {
  apps: [{
    name: 'price-scraper',
    // ... other config
    exp_backoff_restart_delay: 100,
    max_restarts: 10,
    min_uptime: '5m',
    listen_timeout: 8000,
    shutdown_with_message: true
  }]
}

Wrap-Up

Now you've got a complete setup with automatic restarts keeping your app alive 24/7, system boot integration so you never worry about server reboots, real-time monitoring showing you exactly what's happening under the hood, custom metrics tracking whatever matters to your business, health checks catching problems before users do, and centralized log management that actually makes sense - all beautifully visible in your app.pm2.io dashboard