Deploying a trading bot with PM2
ecosystem.config.js, auto-restart, log rotation, and max_memory_restart for running Polymarket bots reliably in production.
Why PM2
PM2 is a Node.js process manager. For trading bots it gives you:
- Auto-restart on crash, with exponential backoff to prevent restart storms.
- Persistent log files with automatic rotation so you do not fill the disk.
- A memory ceiling: if a bot leaks memory and grows past a threshold, PM2 kills and restarts it automatically.
pm2 statusto see all bots at a glance with uptime, restarts, and memory.
Install globally: npm install -g pm2.
ecosystem.config.js
Put this at the root of your predtools directory:
// ecosystem.config.js
module.exports = {
apps: [
{
name: 'poly5m-v4',
script: 'poly5m/poly5m-v4.js',
args: '--asset BTC --live',
cwd: '/home/ubuntu/predtools',
autorestart: true,
max_restarts: 50,
min_uptime: '10s', // must stay up 10s to count as a successful start
max_memory_restart: '200M',
log_file: 'data/pm2-poly5m-v4.log',
merge_logs: true,
time: true, // prepend timestamp to each log line
},
{
name: 'poly15m-v6',
script: 'poly15m/poly15m-v6.js',
args: '--asset BTC --live',
cwd: '/home/ubuntu/predtools',
autorestart: true,
max_restarts: 50,
min_uptime: '10s',
max_memory_restart: '200M',
log_file: 'data/pm2-poly15m-v6.log',
merge_logs: true,
time: true,
},
{
name: 'polycopy',
script: 'polycopy/polycopy.js',
args: '--live --max-balance 50',
cwd: '/home/ubuntu/predtools/polycopy',
autorestart: true,
max_restarts: 50,
min_uptime: '30s', // polycopy needs longer to initialize
max_memory_restart: '400M', // puppeteer uses more memory
log_file: '../data/pm2-polycopy.log',
merge_logs: true,
time: true,
},
{
name: 'bot-monitor',
script: 'poly5m/bot-monitor.js',
cwd: '/home/ubuntu/predtools',
autorestart: true,
max_restarts: 20,
min_uptime: '5s',
max_memory_restart: '100M',
log_file: 'data/pm2-monitor.log',
merge_logs: true,
time: true,
},
],
}Starting and managing
# Start all bots defined in ecosystem.config.js
pm2 start ecosystem.config.js
# Check status
pm2 status
# Live log stream for one bot
pm2 logs poly5m-v4 --lines 50
# Restart a single bot
pm2 restart poly5m-v4
# Stop all
pm2 stop all
# Delete from PM2 registry (doesn't delete files)
pm2 delete allSurviving server reboots
PM2 can save the current process list and restore it on system startup:
# Save current process list
pm2 save
# Generate and install a startup script
pm2 startup
# Then run the command it prints, e.g.:
# sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u ubuntu --hp /home/ubuntuAfter this, all saved processes restart automatically on reboot.
Log rotation
PM2's built-in log rotation prevents logs from growing indefinitely:
pm2 install pm2-logrotate
# Configure
pm2 set pm2-logrotate:max_size 50M
pm2 set pm2-logrotate:retain 7 # keep 7 rotated files
pm2 set pm2-logrotate:compress true # gzip old logs
pm2 set pm2-logrotate:rotateInterval '0 0 * * *' # rotate daily at midnightWatching the restart count
If a bot is restarting frequently, the PM2 status shows the restart count. A count above 5 in a short window indicates a bug, not a transient crash.
pm2 status
# Output:
# ┌─────┬──────────────┬──────────┬──────┬───────────┬──────┬──────────┐
# │ id │ name │ mode │ pid │ status │ ↺ │ memory │
# ├─────┼──────────────┼──────────┼──────┼───────────┼──────┼──────────┤
# │ 0 │ poly5m-v4 │ fork │ 1234 │ online │ 0 │ 45.2mb │
# │ 1 │ polycopy │ fork │ 1235 │ online │ 2 │ 210.5mb │
# └─────┴──────────────┴──────────┴──────┴───────────┴──────┴──────────┘Environment variables in PM2
Do not hardcode secrets in ecosystem.config.js. Instead, use the env key to pass environment variables, and keep sensitive values in the system environment (set via .bashrc or a secrets manager):
{
name: 'poly5m-v4',
script: 'poly5m/poly5m-v4.js',
env: {
NODE_ENV: 'production',
// Don't put private keys here -- use secrets.json or system env
},
}Our bots load credentials from secrets.json at startup. PM2 just needs to know the working directory and script path.
Summary
- Define all bots in
ecosystem.config.jswithautorestart: true,max_memory_restart, andmin_uptime. - Run
pm2 saveandpm2 startupto survive reboots. - Install
pm2-logrotateto prevent disk fill: 50MB max, 7-day retention, compressed. - Use
pm2 logs <name>for live tailing andpm2 statusfor a health dashboard. - Never put private keys in
ecosystem.config.js-- keep them insecrets.json.
Related bots
poly5m-v4 — Split-window momentum BTC scalper
Buy-both-sides Gabagool on 5-min BTC. Picks up cheap YES + NO at $0.49 or less, locks profit when pair stays below $0.98. CLOB v2 / pUSD, polls books every 2s from 10s to 260s.
polycopy — Whale copy-trading bot
Mirrors trades from profitable Polymarket wallets within seconds. Per-whale WR gate ≥55% after 10 trades, 24h stale exit, $0.10 best-bid collapse exit. Adaptive 3s polling after whale activity.