{"id":2234,"date":"2026-07-14T11:18:57","date_gmt":"2026-07-14T11:18:57","guid":{"rendered":"https:\/\/ukspeed.co.uk\/blog\/?p=2234"},"modified":"2026-07-14T11:44:18","modified_gmt":"2026-07-14T11:44:18","slug":"pm2-resurrect-node-js-uk-vps-auto-restart-after-reboot-2026","status":"publish","type":"post","link":"https:\/\/ukspeed.co.uk\/blog\/pm2-resurrect-node-js-uk-vps-auto-restart-after-reboot-2026\/","title":{"rendered":"How to Auto-Restart Node.js Apps After UK VPS Reboot: PM2 Resurrect &#038; pm2.dump 2026 Guide"},"content":{"rendered":"\n<p><strong>PM2 Resurrect UK VPS<\/strong> is the two-command trick every Node.js developer needs to know before shipping to production, because a single unplanned reboot can silently take down your entire API stack without it. PM2 is the Node.js process manager that keeps applications running under load, restarts crashed workers, and \u2014 with <code>pm2 save<\/code> plus <code>pm2 startup<\/code> \u2014 reliably brings every service back after any UK VPS reboot. This guide shows the complete PM2 Resurrect workflow, from installation to auto-restart configuration and monitoring, tested on Ubuntu 24.04 LTS running on a <a href=\"https:\/\/ukspeed.co.uk\/blog\/why-uk-speed-premium-network-is-the-best-choice-for-high-traffic-vps-hosting-in-2026\/\">UK Speed premium network VPS<\/a>.<\/p>\n\n\n\n<figure class=\"uks-svg-fig\" style=\"margin:1.5em 0;text-align:center\">\n<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 720 320\" role=\"img\" aria-label=\"PM2 Resurrect flow on UK VPS: save, startup, resurrect\" style=\"max-width:100%;height:auto\">\n<defs><linearGradient id=\"pmBg\" x1=\"0\" x2=\"0\" y1=\"0\" y2=\"1\"><stop offset=\"0\" stop-color=\"#1a2547\"\/><stop offset=\"1\" stop-color=\"#0f1c3f\"\/><\/linearGradient><\/defs>\n<rect width=\"720\" height=\"320\" fill=\"url(#pmBg)\" rx=\"12\"\/>\n<text x=\"360\" y=\"34\" fill=\"#fbbf24\" font-family=\"Inter,Arial\" font-size=\"18\" font-weight=\"700\" text-anchor=\"middle\">PM2 Resurrect UK VPS \u2014 Boot Recovery Flow 2026<\/text>\n<g font-family=\"Inter,Arial\" font-size=\"12\" fill=\"#e2e8f0\">\n<rect x=\"40\" y=\"70\" width=\"180\" height=\"200\" rx=\"10\" fill=\"#0d9488\" opacity=\"0.92\"\/>\n<text x=\"130\" y=\"98\" text-anchor=\"middle\" fill=\"#fff\" font-size=\"15\" font-weight=\"700\">1. pm2 start<\/text>\n<text x=\"130\" y=\"126\" text-anchor=\"middle\">Launch Node app<\/text>\n<text x=\"130\" y=\"146\" text-anchor=\"middle\">Cluster mode<\/text>\n<text x=\"130\" y=\"166\" text-anchor=\"middle\">Auto-restart on crash<\/text>\n<text x=\"130\" y=\"188\" text-anchor=\"middle\" fill=\"#5eead4\">pm2 start app.js<\/text>\n<text x=\"130\" y=\"210\" text-anchor=\"middle\" fill=\"#5eead4\">-i max &#8211;name api<\/text>\n<rect x=\"240\" y=\"70\" width=\"180\" height=\"200\" rx=\"10\" fill=\"#ea580c\" opacity=\"0.92\"\/>\n<text x=\"330\" y=\"98\" text-anchor=\"middle\" fill=\"#fff\" font-size=\"15\" font-weight=\"700\">2. pm2 save<\/text>\n<text x=\"330\" y=\"126\" text-anchor=\"middle\">Snapshot process list<\/text>\n<text x=\"330\" y=\"146\" text-anchor=\"middle\">Write dump.pm2<\/text>\n<text x=\"330\" y=\"166\" text-anchor=\"middle\">~\/.pm2\/dump.pm2<\/text>\n<text x=\"330\" y=\"188\" text-anchor=\"middle\" fill=\"#fed7aa\">pm2 save<\/text>\n<rect x=\"440\" y=\"70\" width=\"180\" height=\"200\" rx=\"10\" fill=\"#7c3aed\" opacity=\"0.92\"\/>\n<text x=\"530\" y=\"98\" text-anchor=\"middle\" fill=\"#fff\" font-size=\"15\" font-weight=\"700\">3. pm2 startup<\/text>\n<text x=\"530\" y=\"126\" text-anchor=\"middle\">Generate systemd unit<\/text>\n<text x=\"530\" y=\"146\" text-anchor=\"middle\">Install boot hook<\/text>\n<text x=\"530\" y=\"166\" text-anchor=\"middle\">Enable systemctl<\/text>\n<text x=\"530\" y=\"188\" text-anchor=\"middle\" fill=\"#e9d5ff\">pm2 startup<\/text>\n<text x=\"530\" y=\"210\" text-anchor=\"middle\" fill=\"#e9d5ff\">systemctl enable pm2<\/text>\n<text x=\"360\" y=\"298\" text-anchor=\"middle\" fill=\"#fbbf24\" font-weight=\"700\" font-size=\"13\">On reboot: systemd \u2192 pm2 resurrect \u2192 apps online in seconds<\/text>\n<\/g>\n<\/svg>\n<figcaption style=\"font-size:13px;color:#64748b;margin-top:6px\">The three-step PM2 Resurrect workflow every Node.js production on UK VPS needs.<\/figcaption>\n<\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Why Node.js Apps Need PM2 Resurrect on UK VPS<\/h2>\n\n\n\n<p>A Node.js app started with <code>node server.js<\/code> dies the moment the SSH session ends, the process crashes, or the UK VPS reboots. In production, none of those events should ever bring down your API. PM2 solves crash restart automatically, but that alone does not survive a reboot \u2014 after a fresh boot, PM2 itself is not running, and without <code>pm2 save<\/code> plus <code>pm2 startup<\/code>, every Node.js service must be manually started. PM2 Resurrect closes this final gap: on any reboot, systemd starts PM2, PM2 reads its saved dump, and every app comes back exactly as it was.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How PM2 Resurrect Manages Node.js Processes in Production<\/h2>\n\n\n\n<p>PM2 is a single Node.js binary that runs as a daemon and supervises child processes. It handles clustering (fork mode or cluster mode across all CPU cores), automatic restart on crash, log aggregation, memory and CPU limits, and graceful reload for zero-downtime deploys. Under the hood, PM2 maintains a list of managed apps with their environment, working directory, and restart policy \u2014 everything needed to reconstruct the runtime state. On a modest 4 vCPU UK Speed NVMe VPS, PM2 comfortably supervises 10-20 Node.js processes, matching the performance profile of the <a href=\"https:\/\/ukspeed.co.uk\/blog\/uk-speed-vps-nvme-vs-ssd-real-benchmark-for-wordpress-woocommerce-in-2026\/\">VPS NVMe tier<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Install PM2 on Ubuntu 24.04 UK VPS<\/h2>\n\n\n\n<p>Install Node.js 22 LTS from NodeSource: <code>curl -fsSL https:\/\/deb.nodesource.com\/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs<\/code>. Verify with <code>node --version<\/code>. Then install PM2 globally: <code>sudo npm install -g pm2@latest<\/code>. Confirm with <code>pm2 --version<\/code>. Best practice is to run PM2 under a dedicated non-root user like <code>appuser<\/code> \u2014 this contains any compromise to that user&#8217;s home directory. Create the user with <code>adduser appuser<\/code>, switch to it with <code>sudo -iu appuser<\/code>, and install your Node.js app files under <code>\/home\/appuser<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using pm2 save and pm2.dump for State Persistence<\/h2>\n\n\n\n<p>Start your Node.js app with PM2: <code>pm2 start app.js --name api-server -i max<\/code>. The <code>-i max<\/code> flag runs one instance per CPU core in cluster mode, giving free horizontal scaling on the same VPS. Verify with <code>pm2 list<\/code> that the app shows online. Then run <code>pm2 save<\/code>. This writes <code>~\/.pm2\/dump.pm2<\/code> \u2014 a JSON snapshot of every running app with its exact command, environment, and cluster settings. Any time you change the app list (new app, deleted app, changed args), run <code>pm2 save<\/code> again. Skipping this step is the number-one cause of &#8220;apps disappear after reboot&#8221; tickets.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Set Up PM2 Resurrect for Automatic Boot Recovery<\/h2>\n\n\n\n<p>Run <code>pm2 startup<\/code>. PM2 detects your init system (systemd on modern Ubuntu, Debian, and Rocky Linux) and prints a single <code>sudo env PATH=... pm2 startup systemd -u appuser --hp \/home\/appuser<\/code> command. Copy and paste that command exactly \u2014 it installs a systemd unit file at <code>\/etc\/systemd\/system\/pm2-appuser.service<\/code> that starts PM2 at boot under your app user. Enable and verify with <code>sudo systemctl status pm2-appuser<\/code>. From this point, every reboot triggers systemd \u2192 PM2 \u2192 <code>pm2 resurrect<\/code>, which reads the dump and starts every app.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How PM2 Resurrect Works After a UK VPS Reboot<\/h2>\n\n\n\n<p>The PM2 Resurrect chain runs in this order: systemd starts the pm2 unit \u2192 PM2 daemon boots \u2192 PM2 reads <code>dump.pm2<\/code> \u2192 each app process starts in cluster or fork mode \u2192 PM2 begins restart-on-crash supervision. The whole sequence completes in 3-8 seconds on a UK Speed NVMe VPS. Because Node.js apps typically boot in under a second, your API is live essentially at kernel-ready. Combined with <a href=\"https:\/\/ukspeed.co.uk\/blog\/unmetered-traffic-vps-explained-why-port-speed-based-bandwidth-is-better-than-monthly-tb-limits\/\">unmetered UK VPS bandwidth<\/a>, the reboot recovery pattern is bulletproof even when a viral event drives massive traffic immediately after restart.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing PM2 Resurrect with a Real Server Reboot<\/h2>\n\n\n\n<p>Never trust a PM2 Resurrect configuration without testing it. Confirm apps are running, run <code>pm2 save<\/code>, then <code>sudo reboot<\/code> the VPS. Reconnect via SSH after 30 seconds and run <code>pm2 list<\/code> to confirm PM2 Resurrect worked \u2014 every app should be back with a fresh uptime counter and zero restarts. If any app is missing, check <code>journalctl -u pm2-appuser -e<\/code> for the boot-time error. Common causes: forgot to <code>pm2 save<\/code> after adding an app, PM2 startup running as the wrong user, or the app directory unreadable due to disk mount timing. Similar patterns work well inside <a href=\"https:\/\/ukspeed.co.uk\/blog\/docker-compose-wordpress-production-on-uk-vps-full-stack-setup-guide-2026\/\">Docker Compose stacks on UK VPS<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Use PM2 Ecosystem File for Reproducible Deploys<\/h2>\n\n\n\n<p>Command-line flags work for one-off starts, but production UK VPS deployments live in <code>ecosystem.config.js<\/code>. This file declares every app your PM2 instance manages \u2014 name, script, cwd, env, instances, exec_mode, max_memory_restart, log paths, and restart policy \u2014 as version-controlled JavaScript. Start the whole fleet with <code>pm2 start ecosystem.config.js --env production<\/code>. The <code>--env<\/code> flag activates named environment blocks so the same file drives staging and production with different <code>NODE_ENV<\/code> and secrets. Because the file lives in git, every teammate deploys the same stack with the same tuning, and disaster recovery on a new UK VPS is one <code>git clone && pm2 start ecosystem.config.js<\/code> away from full restoration.<\/p>\n\n\n\n<p>Combine the ecosystem file with an <code>EnvironmentFile=\/home\/appuser\/.env.production<\/code> loaded by the systemd wrapper so secrets never end up committed to the repo. PM2 reads them at process start via <code>process.env<\/code>, giving your Node.js code the same runtime shape across staging and production.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Monitoring Node.js Apps with PM2 Metrics<\/h2>\n\n\n\n<p><code>pm2 monit<\/code> opens a real-time terminal dashboard showing CPU, memory, and event loop lag per process. For historical monitoring, use PM2 Plus&#8217;s free tier or expose PM2 metrics on a local port and scrape them with Prometheus. Set memory restart limits with <code>--max-memory-restart 500M<\/code> \u2014 PM2 gracefully restarts any process that exceeds 500 MB, preventing runaway memory leaks. Set <code>--restart-delay 3000<\/code> to add a three-second cooldown between restarts, avoiding thrashing when a bug causes constant crashes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to Zero-Downtime Deploy with PM2 Reload<\/h2>\n\n\n\n<p>Beyond PM2 Resurrect, the final PM2 production skill: <code>pm2 reload api-server<\/code> restarts your app in cluster mode by shutting down old workers one at a time as new ones come online, with zero dropped connections. Compare to <code>pm2 restart<\/code> which kills all workers simultaneously \u2014 a brief outage. Zero-downtime reload works because cluster mode has multiple workers behind PM2&#8217;s internal load balancer; a rolling restart keeps requests flowing. Combine with <a href=\"https:\/\/ukspeed.co.uk\/blog\/how-to-achieve-sub-100ms-ttfb-on-uk-wordpress-complete-server-side-optimization-guide-2026\/\">sub-100ms TTFB optimizations<\/a> and your Node.js API on UK VPS matches the operational quality of managed platforms costing 10x more.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Troubleshooting Common PM2 Resurrect Failures<\/h2>\n\n\n\n<p>Three failures cover 90% of &#8220;apps did not come back&#8221; tickets. First, forgetting <code>pm2 save<\/code> after adding a new app \u2014 the dump is stale, and only the previously-saved apps resurrect. Second, permission issues on <code>~\/.pm2<\/code> \u2014 running <code>pm2 startup<\/code> as root but then running apps as another user creates the wrong dump path. Third, database or Redis unreachable at boot \u2014 the app crashes on startup because its dependency is not yet ready; fix with <code>Requires=<\/code> and <code>After=<\/code> in the PM2 systemd unit. For deeper context, see the <a href=\"https:\/\/pm2.keymetrics.io\/docs\/usage\/startup\/\" rel=\"noopener\">official PM2 startup documentation<\/a>.<!-- uks-auto-extlink: intentionally suppressed by author --><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion: Production Node.js on UK VPS<\/h2>\n\n\n\n<p>PM2 Resurrect turns a Node.js app from a fragile foreground process into a boot-resilient production service. Three commands \u2014 <code>pm2 start<\/code>, <code>pm2 save<\/code>, <code>pm2 startup<\/code> \u2014 and every reboot brings every service back automatically. Pair with UK Speed&#8217;s fast NVMe storage and premium network, and your Node.js stack matches managed hosting reliability at a fraction of the cost.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>PM2 Resurrect UK VPS is the two-command trick every Node.js developer needs to know before shipping to production, because a single unplanned reboot can\u2026<\/p>\n","protected":false},"author":3,"featured_media":2242,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[105],"tags":[299,143,147,61,146,145,113,136,140],"class_list":["post-2234","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-backup","tag-database","tag-docker","tag-hosting","tag-linux","tag-nvme","tag-performance","tag-ssl","tag-vps"],"_links":{"self":[{"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=2234"}],"version-history":[{"count":1,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2234\/revisions"}],"predecessor-version":[{"id":2241,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/posts\/2234\/revisions\/2241"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/media\/2242"}],"wp:attachment":[{"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=2234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=2234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ukspeed.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=2234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}