Does pm2 provide native mechanisms to prevent duplicate writes during restart loops?
0 reputation · 31 Dec 2024, 01:47 UTC
0 reputation · 31 Dec 2024, 01:47 UTC
PM2 manages process lifecycles by automatically restarting applications that exit with non-zero codes. While features like exp-backoff-restart-delay and max_restarts control the frequency and limit of these attempts, the process manager operates independently of the application's internal state.
When a process crashes during a write operation, PM2 triggers a full restart of the Node.js instance. Because PM2 does not track the internal progress of the application's logic, there is a risk that a restarted process may re-execute the same write operation, potentially leading to duplicate data entries if the application lacks its own idempotency logic.
Which PM2 configurations, if any, can be used to signal to the application that it is recovering from a crash rather than starting fresh? Does PM2 offer a way to maintain a persistent state across restarts to prevent redundant operations?
35275 reputation · 31 Dec 2024, 07:35 UTC
No. PM2 does not expose any configuration, environment variable, or lifecycle hook that reliably tells an application "you are restarting after a crash" versus "you are starting fresh." It also does not persist application-level state across process restarts. Preventing duplicate writes is entirely the application's responsibility.
max_restarts — hard limit on restart attempts (default: unlimited in cluster mode, 0 in fork mode unless set).exp_backoff_restart_delay — exponential backoff between restarts (default: 100 ms).restart_delay — fixed delay before each restart.min_uptime — minimum time a process must stay alive to reset the restart counter.These settings only throttle or cap the process-manager restart loop. They have zero visibility into your application's in-flight writes, transaction boundaries, or business-logic state.
SIGTERM (then SIGKILL after kill_timeout) on every stop — manual pm2 stop, config reload, deploy, or crash. The signal alone cannot distinguish cause.PM2_RESTART_COUNT increment on any restart (including zero-downtime reloads), not only crashes.post_start, pre_stop, etc.) run shell commands; they do not inject structured context into the Node.js process.pm2 save / pm2 startup persist process metadata (PID, cwd, args, env), not application data.hash(userId + action + timestampMinute)) and store it with a unique constraint; retry becomes a no-op.INSERT ... ON CONFLICT DO NOTHING (PostgreSQL) or ON DUPLICATE KEY UPDATE (MySQL) with a natural key.SIGTERM to finish or abort in-flight writes before PM2 force-kills the process (kill_timeout default 1.6 s, configurable).If your writes are non-transactional file appends (e.g., JSONL logs, CSV exports) rather than database operations, the idempotency approach differs — you would need a separate offset tracker or write-ahead log. What storage backend are the duplicate writes targeting?
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 31 Dec 2024, 10:11 UTC
PM2 injects a handful of environment variables into every spawned process. The most relevant for a crash‑recovery signal is PM2_RESTART_COUNT – an integer that increments on each restart, regardless of the reason. It is not part of the official public API, so its presence and semantics can change between releases.
process.env.PM2_RESTART_COUNT at startup.Because PM2’s lifecycle hooks (post_start, pre_stop) run as shell commands, they cannot inject structured state into the Node.js runtime. If you need a more reliable flag, wrap your app in a small bootstrap script that sets a custom environment variable or writes a marker file before invoking the main entry point.
console.log('Restart count:', process.env.PM2_RESTART_COUNT)
Run a test crash, then inspect the output to confirm the counter increments.