Which upgrade path preserves state for a small Erlang app during zero‑downtime migration?
0 reputation · 30 Aug 2020, 20:11 UTC
0 reputation · 30 Aug 2020, 20:11 UTC
Upgrade a lightweight OTP application in a production cluster while keeping all nodes online.
Stateful gen_server modules must survive the code change, dependencies must be pinned to avoid mismatched BEAM images, and the upgrade path must be reproducible.
OTP’s release_handler offers a standard --upgrade workflow but its default strategy may leave stale modules in memory and relies on code_change/3 callbacks. A hand‑crafted deployment script can explicitly purge and load new modules, but adds complexity and requires manual coordination.
release_handler’s built‑in upgrade or a custom script—provides stronger guarantees for preserving in‑memory state across gen_server restarts?release_handler but injects a custom code_change/3 callback improve reliability?The built‑in release_handler upgrade path (appup/relup) preserves in‑memory gen_server state when you provide proper code_change/3 callbacks and pin dependencies.
release_handler coordinates suspending processes, loading the new module, invoking code_change/3, and resuming them, guaranteeing that no process runs a mixture of old and new code.appup file works for any node in the cluster, eliminating hand‑script drift.If your application relies on state that must survive a node migration (e.g., in‑memory data that cannot be rebuilt locally), you will need external replicated storage before this path is sufficient.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 31 Aug 2020, 06:12 UTC
The release_handler:upgrade/2 command keeps existing gen_server processes alive and invokes their code_change/3 callback, so in‑memory state is preserved only when that callback correctly transforms the old state to the new format. A custom script that purges and loads modules does not by itself preserve process state—purging forces the VM to drop old code, causing any process still referencing it to crash or be restarted, losing state unless the state has been externalized or handed off. Therefore, for zero‑downtime upgrades of a small OTP app, rely on the built‑in upgrade path and ensure each stateful module’s code_change/3 returns {ok, NewState}; verify with sys:get_state/1 before and after the upgrade.