What Is a Supervisor?
A supervisor is an OTP behaviour whose entire job is to start, monitor, and restart a defined set of child processes according to a configured strategy. Under the hood it uses ordinary links and trap_exit — a supervisor links to every child it starts and traps their exit signals, turning each child crash into an event it can react to programmatically. Every supervisor module implements init/1, which must return {ok, {SupFlags, ChildSpecs}}, declaring both the restart strategy and the list of children it is responsible for.
Cricket analogy: A fielding captain stationed at mid-on who keeps a constant eye on every fielder's position and immediately repositions anyone who drifts out of place functions like a supervisor process watching over its children via links, ready to react to any failure.
Restart Strategies: one_for_one, one_for_all, rest_for_one
OTP supervisors offer three core restart strategies. one_for_one restarts only the specific child that crashed, leaving its siblings untouched — appropriate when children are independent. one_for_all terminates and restarts every child under the supervisor whenever any single one crashes — appropriate when children share tightly coupled state that must be reset together. rest_for_one restarts the crashed child plus every child that was started after it in the child list, but leaves children started before it alone — appropriate when later children depend on earlier ones but not vice versa.
Cricket analogy: one_for_one is like replacing only the injured fielder while the rest of the team continues unchanged; one_for_all is like a full team reshuffle after any one player's injury disrupts the whole fielding plan; rest_for_one is like reshuffling only the batting order from the injured player's slot onward.
-module(worker_sup).
-behaviour(supervisor).
-export([start_link/0, init/1]).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
init([]) ->
SupFlags = #{strategy => one_for_one,
intensity => 5,
period => 10},
ChildSpec = #{id => worker,
start => {worker, start_link, []},
restart => permanent,
shutdown => 5000,
type => worker,
modules => [worker]},
{ok, {SupFlags, [ChildSpec]}}.
Child Specifications and Restart Types
Each entry in the ChildSpecs list is a map with fields including id, start (the module/function/args to launch the child), restart, shutdown, and type. The restart field determines the child's restart policy: permanent children are always restarted no matter how they exit, including a normal exit; temporary children are never restarted, regardless of exit reason; transient children are restarted only if they exit abnormally, and left alone if they exit normally or via shutdown.
Cricket analogy: A permanent all-rounder like Ravindra Jadeja is always recalled to the squad regardless of how the previous match went, mirroring restart: permanent, which always restarts the child on any exit; a net bowler brought in just for one session and never recalled mirrors restart: temporary.
SupFlags' intensity and period fields (e.g., intensity => 5, period => 10) cap restarts to at most 5 within any rolling 10-second window. This stops a persistently crashing child from being restarted forever, which would burn CPU and hide a real underlying bug.
Supervision Trees and Escalation
Supervisors are not limited to supervising ordinary worker processes — a supervisor can itself be a child of another supervisor, forming a supervision tree. This lets a system decompose fault tolerance concerns into layers: a leaf-level supervisor handles frequent, expected restarts of individual workers, while higher-level supervisors only get involved when an entire subtree can't stabilize. If a supervisor's own children exceed its configured intensity within period, the supervisor concludes the failures aren't transient, terminates itself, and lets its own parent supervisor decide what to do next.
Cricket analogy: A domestic cricket board overseeing multiple state associations, where if a state association itself collapses beyond repair, the issue escalates to the national board to intervene, mirrors how a supervisor exceeding its own restart intensity terminates and escalates to its parent supervisor.
Setting restart intensity too high (or period too long) can mask a genuine bug by letting a process crash-loop many times before the supervisor gives up, flooding logs and wasting resources while the root cause goes unaddressed. Tune intensity/period to match how quickly a real transient failure should resolve.
- A supervisor is an OTP behaviour that starts, monitors, and restarts a set of child processes according to a defined strategy.
- init/1 must return {ok, {SupFlags, ChildSpecs}} describing the restart strategy and each child's specification.
- one_for_one restarts only the failed child; one_for_all restarts every child; rest_for_one restarts the failed child and all children started after it.
- Each child spec's restart field (permanent, temporary, transient) controls whether and when that child is restarted.
- intensity and period in SupFlags cap how many restarts are allowed within a time window before the supervisor itself gives up and exits.
- Supervisors can supervise other supervisors, forming a tree, so failures escalate upward if a subtree can't stabilize.
- Supervision trees are the structural backbone of OTP fault tolerance, separating 'what can fail' from 'how to recover.'
Practice what you learned
1. What must a supervisor's init/1 callback return?
2. Which restart strategy restarts every child whenever any one child terminates abnormally?
3. A child spec's restart field is set to `temporary`. What does that mean?
4. What happens when a supervisor exceeds the maximum restart intensity defined in its SupFlags?
5. In rest_for_one strategy, if the third of five children crashes, which children are restarted?
Was this page helpful?
You May Also Like
spawn and Links
Understand how Erlang creates new processes with spawn and how links create bidirectional failure-propagation relationships between them.
gen_server Behaviour
Master the gen_server OTP behaviour — the standard pattern for building stateful, message-handling server processes with synchronous and asynchronous calls.
Fault Tolerance: Let It Crash
Explore Erlang's 'let it crash' philosophy — why defensive programming is often avoided in favor of fast failure and supervisor-driven recovery.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics