| Runtime |
Static Go binary — 2.6 MB, zero deps |
Node.js + npm package — 26 MB, 5,000+ files |
| Supervised languages |
Any executable — Node, Python, Go, Rust, PHP, Ruby, C/C++, Bash, Deno, Bun… |
Node-first; other languages need a wrapper interpreter script |
| Daemon footprint (idle) |
~16 MB RSS supervising 5 workers |
~86 MB RSS supervising 2 workers |
| Reverse proxy (HTTP/WS/TCP/UDP) |
Built in — round-robin, session migration on restart |
External — requires nginx or HAProxy |
| Rate limiting & firewall |
Built in (Vanguard): token bucket, IP banlists, CDN trust, path bans |
External — requires nginx, fail2ban, Cloudflare, or middleware |
| TLS termination |
Built in — HTTPS/WSS, mTLS, bring your own certs |
External — requires nginx or app-level |
| Cross-language IPC |
Channels + persistent streams, routed by daemon, identical API in Node/Python/PHP/Perl/Lua |
pm2.launchBus — Node-only, axon-based |
| File watcher |
Native inotify, per-worker regex, debounced, one tree |
chokidar — historically CPU-heavy on large repos (issue history) |
| Zero-downtime rolling restart |
Default for any worker type with a shared listener |
Node cluster mode only (pm2 reload) |
| GUI / dashboard |
Local live GUI shipped in-binary at :6789 |
PM2+ SaaS (paid) or third-party dashboards |
| Config format |
apm.conf (nginx-style) or CLI flags |
ecosystem.config.js or CLI flags |
| Persistent state |
One config file. No hidden dump file. |
~/.pm2/dump.pm2 + pm2 save / resurrect |
| Install |
curl … | bash — one file to /usr/sbin/apm |
npm i -g pm2 — requires Node.js + npm already installed |
| License |
Free to use (binary); source proprietary |
AGPL-3.0 (core); PM2+ is a paid SaaS |