Process Lifecycle
Process states, transitions, shutdown flow, and lifecycle hooks.
Understanding the process lifecycle helps you configure restart policies, health checks, and hooks effectively.
States
| State | Description |
|---|---|
| Starting | Process has been spawned. If a health check is configured, pm3 is waiting for it to pass. |
| Online | Process is running and healthy. |
| Unhealthy | Health check failed (timed out after 30 seconds). |
| Stopped | Process was stopped by user command or exited cleanly. |
| Errored | Process failed to start or crashed unexpectedly. |
State Transitions
| From | Event | To |
|---|---|---|
| (spawn) | Process starts | Starting |
| Starting | Health check passes | Online |
| Starting | No health check configured | Online |
| Starting | Health check times out (30s) | Unhealthy |
| Online | Exit / signal / user stop | Stopped |
| Stopped | Restart (policy or manual) | Starting |
| (spawn) | Spawn failure | Errored |
Graceful Shutdown
When a process is stopped (via pm3 stop, pm3 restart, or other triggers):
- Send
kill_signal— Default:SIGTERM. Configurable per process. - Wait
kill_timeout— Default: 5000ms (5 seconds). - Force
SIGKILL— If the process hasn't exited after the timeout. - Run
post_stophook — If configured.
[web]
command = "node server.js"
kill_signal = "SIGINT" # Send SIGINT instead of SIGTERM
kill_timeout = 10000 # Wait 10 seconds before SIGKILL
post_stop = "echo 'web shutdown complete'"Lifecycle Hooks
pre_start
Runs before the process spawns. Executed via sh -c.
- If the hook fails (non-zero exit), the process will not start.
- Output is captured in the process's log files.
[api]
command = "python app.py"
pre_start = "python manage.py migrate"post_stop
Runs after the process stops. Executed via sh -c.
- Runs regardless of how the process stopped (user command, crash, signal).
- Output is captured in the process's log files.
[worker]
command = "node worker.js"
post_stop = "node cleanup.js"Restart Behavior
When a process exits, the restart policy determines what happens:
| Policy | Behavior |
|---|---|
on_failure (default) | Restart on non-zero exit (unless exit code is in stop_exit_codes) |
always | Always restart, regardless of exit code |
never | Never restart |
Exponential Backoff
When restarting, pm3 uses exponential backoff to avoid rapid restart loops:
| Restart # | Delay |
|---|---|
| 1 | 100ms |
| 2 | 200ms |
| 3 | 400ms |
| 4 | 800ms |
| 5 | 1.6s |
| ... | ... |
| n | min(100ms × 2^n, 30s) |
The delay is capped at 30 seconds.
Restart Counter Reset
The restart counter resets to zero when the process stays running for at least min_uptime milliseconds (default: 1000ms). If max_restarts is reached (default: 15), pm3 stops trying to restart the process.
Dependency Ordering
Processes with depends_on are started and stopped in dependency order:
- Start: Dependencies start first. A process waits for its dependencies to be running.
- Stop: Dependents stop first, then their dependencies.
[database]
command = "docker start postgres"
[api]
command = "python app.py"
depends_on = ["database"]
[web]
command = "npm start"
depends_on = ["api"]Start order: database → api → web
Stop order: web → api → database