{"slug":"tako-vs-pm2-and-nginx","url":"https://tako.sh/blog/tako-vs-pm2-and-nginx/","canonical":"https://tako.sh/blog/tako-vs-pm2-and-nginx/","title":"Tako vs PM2 + Nginx","date":"2026-04-21T01:34","description":"PM2 + Nginx is the quiet default for self-hosted Node — a stack of four tools glued together with shell scripts. Tako collapses it into one CLI.","author":null,"image":"6c18d3fdbea8","imageAlt":null,"headings":[{"depth":2,"slug":"at-a-glance","text":"At a glance"},{"depth":2,"slug":"where-pm2--nginx-shines","text":"Where PM2 + Nginx shines"},{"depth":2,"slug":"where-tako-is-different","text":"Where Tako is different"},{"depth":3,"slug":"one-binary-instead-of-four-tools","text":"One binary instead of four tools"},{"depth":3,"slug":"a-proxy-that-knows-about-deploys","text":"A proxy that knows about deploys"},{"depth":3,"slug":"secrets-arent-env-vars","text":"Secrets aren’t env vars"},{"depth":3,"slug":"scale-to-zero","text":"Scale-to-zero"},{"depth":3,"slug":"local-dev-that-matches-production","text":"Local dev that matches production"},{"depth":3,"slug":"workflows-and-queues-not-just-processes","text":"Workflows and queues, not just processes"},{"depth":2,"slug":"different-ambitions","text":"Different ambitions"}],"markdown":"Before Docker, before Kubernetes, before the whole self-hosted PaaS genre showed up, there was a stack that shipped a lot of Node apps: [PM2](https://github.com/Unitech/pm2) keeping processes alive, Nginx out front for TLS and routing, a `.env` file for secrets, and a small pile of shell scripts holding it all together. PM2 has 42k+ GitHub stars and over a decade of production use. Nginx powers a huge slice of the internet. The combo has been the quiet default for self-hosted Node.js for years, and plenty of production apps still run on it today.\n\nTako collapses that stack into a single CLI. We think the philosophy is still right — a VPS and a good tool should be enough — but the shape of \"a good tool\" can be a lot more cohesive.\n\n## At a glance\n\n|                        | **PM2 + Nginx**                         | **Tako**                                               |\n| ---------------------- | --------------------------------------- | ------------------------------------------------------ |\n| **Number of tools**    | PM2, Nginx, certbot, shell scripts      | `tako` CLI + `tako-server`                             |\n| **Proxy**              | Nginx (C)                               | Pingora (Rust, Cloudflare)                             |\n| **Process manager**    | PM2                                     | Built into `tako-server`                               |\n| **TLS**                | certbot + Let's Encrypt, manual renewal | Built-in ACME ([`tako.toml`](/docs/tako-toml))         |\n| **Config**             | `ecosystem.config.js` + `nginx.conf`    | TOML ([`tako.toml`](/docs/tako-toml))                  |\n| **Deploys**            | rsync / git pull + shell scripts        | `tako deploy` → SFTP + rolling restart                 |\n| **Zero-downtime**      | `pm2 reload` (processes only)           | Pingora-coordinated rolling restart                    |\n| **Secrets**            | `.env` files on disk                    | AES-256-GCM, delivered via fd 3                        |\n| **Scale-to-zero**      | No                                      | Yes, with cold start                                   |\n| **Local dev**          | None                                    | Built-in HTTPS + DNS ([`tako dev`](/docs/development)) |\n| **Workflows / queues** | None (BYO Redis + BullMQ)               | Built into `tako-server`                               |\n| **Multi-server**       | Script it yourself                      | Declarative per-environment                            |\n| **Stars**              | PM2 ~42k                                | New kid on the block                                   |\n\n## Where PM2 + Nginx shines\n\nThis stack has earned its longevity. PM2 does one job very well: it keeps your Node process alive, restarts on crash, runs in cluster mode to use every core, and gives you `pm2 reload` for zero-downtime process restarts. The CLI is fast, the logs are readable, and you can inspect a running app in seconds.\n\nNginx is Nginx. It's been the reference reverse proxy for over two decades. TLS termination is battle-tested, and `certbot --nginx` wires up Let's Encrypt in one command. If you know your way around `/etc/nginx/sites-available`, you can route any set of domains to any set of upstreams with surgical precision.\n\nThe combo also has the virtue of familiarity. Any senior backend engineer has touched both tools. Tutorials are everywhere. Debugging is well-trodden territory. For a single app on a single server, there's a lot to like.\n\n## Where Tako is different\n\n### One binary instead of four tools\n\nThe DIY stack is really four or five tools glued together: PM2 for processes, Nginx for TLS and routing, certbot for certificates, a `.env` file for secrets, and a shell script (or Makefile, or GitHub Action) to tie it all together. Each has its own config format, its own upgrade cadence, and its own failure modes. Nothing enforces that they agree — a new domain in `nginx.conf` doesn't automatically show up in your deploy script, and a new env var in `.env` doesn't automatically reach PM2.\n\nTako is a single Rust binary on the server (`tako-server`) and a single CLI on your laptop (`tako`). [`tako.toml`](/docs/tako-toml) declares processes, routes, TLS, and scaling in one file. The Pingora proxy, the process supervisor, secrets, and rolling restarts are coordinated by the same binary. There's nothing to glue together.\n\n### A proxy that knows about deploys\n\nNginx terminates TLS and reverse-proxies requests; it doesn't know anything about your deployment. Zero-downtime updates mean orchestrating from outside: spin up new processes on new ports, health-check them, rewrite `upstream` blocks, `nginx -s reload`, then kill the old processes. `pm2 reload` handles the process side, but the proxy-side coordination is on you.\n\nTako uses [Pingora](/blog/pingora-vs-caddy-vs-traefik) — Cloudflare's Rust proxy framework — and the proxy is aware of the deploy state. New instances come up and register themselves; Pingora health-checks them, shifts traffic, then drains the old ones. No config reload, no race conditions, no scripts.\n\n```d2\ndirection: right\n\ndiy: PM2 + Nginx {\n  direction: down\n  scripts: Deploy scripts\n  pm2: PM2\n  nginx: Nginx\n  certbot: certbot\n\n  scripts -> pm2: restart procs\n  scripts -> nginx: rewrite config\n  certbot -> nginx: renew certs\n}\n\ntako: Tako {\n  direction: down\n  cli: tako CLI\n  server: tako-server\n\n  cli -> server: SFTP + deploy\n  server -> server: Pingora + procs + TLS\n}\n```\n\n### Secrets aren't env vars\n\nThe standard pattern is a `.env` file on the server, read into `process.env` at startup. It works, but `.env` sits on disk, and environment variables inherit into any subprocess your app spawns — including children you didn't write.\n\nTako encrypts secrets locally with AES-256-GCM, ships them to the server where they live in an encrypted SQLite store, and hands them to each instance through [file descriptor 3](/blog/secrets-without-env-files) at spawn time. They never touch disk on the server and they don't leak to subprocesses.\n\n### Scale-to-zero\n\nPM2 keeps every registered process running. That's the right default for always-on apps, but if you're running staging environments, internal dashboards, and a few low-traffic side projects on the same VPS, they all eat memory 24/7.\n\nTako supports [on-demand scaling](/docs/how-tako-works): apps spin down after an idle timeout and cold-start on the next request. On a single [$5 VPS running multiple apps](/blog/your-5-dollar-vps-is-more-powerful-than-you-think), that's real memory savings.\n\n### Local dev that matches production\n\nPM2 is a production tool. Local dev is usually `npm run dev` plus whatever your framework hands you, and HTTPS during development is somebody else's problem.\n\n[`tako dev`](/docs/development) runs your app with real HTTPS, local DNS (`*.test`), and the same SDK and process model that run in production. What works locally works the same way when deployed.\n\n### Workflows and queues, not just processes\n\nPM2 runs whatever process you give it. If your app needs durable background jobs, you wire up Redis + BullMQ (or Sidekiq-style equivalents) yourself. If you want WebSockets at scale, that's another service.\n\nTako ships [durable workflows](/blog/durable-workflows-are-here) inside `tako-server`, with [scale-to-zero workers](/blog/workflow-workers-scale-to-zero) so idle queues cost nothing. [Channels for WebSocket and SSE](/blog/durable-channels-built-in), queues, and image optimization are on the roadmap — all in the same binary that's already running your app.\n\n## Different ambitions\n\nPM2 + Nginx is a stack you assemble. Each tool is excellent at its one job, and the seams between them are yours to own. For a seasoned engineer running one app on one VPS, it's still a reasonable answer — and it'll keep working for years.\n\nTako is a platform. Today that's deployment, routing, TLS, secrets, workflows, and local dev, all in one binary. Tomorrow it's channels, queues, and image optimization. Combined with [multi-server environments](/docs/deployment) and Cloudflare smart routing, you can [build your own edge network](/blog/build-your-own-edge-network-on-commodity-hardware) on cheap VPS boxes worldwide.\n\nThe question isn't whether PM2 + Nginx works — it does. The question is how many seams you want to own, and what you want your infrastructure to do on top of just running the process. Check out [how Tako works](/docs/how-tako-works) to see the architecture, or the [CLI docs](/docs/cli) to give it a try."}