Creating Processes with spawn
The spawn/1 (or spawn/3 for a module/function/args form) built-in function creates a brand-new process running the given function and immediately returns its process identifier, a Pid, to the caller. Critically, spawn by itself establishes no relationship between the new process and its creator — the BEAM VM does not enforce a parent-child hierarchy — so if the spawned process crashes, the process that spawned it is never automatically notified unless a link or monitor is explicitly set up.
Cricket analogy: A franchise like Mumbai Indians signing a new net bowler for practice doesn't require the head coach's constant supervision structure to be defined upfront — the player (process) exists and is assigned a squad number (Pid) the moment they're signed, before any reporting lines are set.
Links and Exit Signal Propagation
Calling link/1 on a Pid — or using spawn_link/1,3 to create and link a process atomically in one step — establishes a bidirectional relationship between the two processes. By default, if either linked process terminates with an abnormal exit reason (anything other than normal), an exit signal propagates to the other, which also terminates, receiving the same reason. This propagation is what allows a crash to cascade cleanly through a set of tightly coupled processes rather than leaving orphaned, half-broken state behind.
Cricket analogy: Two batsmen at the crease running between wickets are linked — if one gets run out attempting a risky single, it directly affects the partnership's fate, just as a linked Erlang process's abnormal exit propagates to terminate its partner.
-module(link_demo).
-export([start/0, trapping_parent/0]).
start() ->
process_flag(trap_exit, true),
Child = spawn_link(fun() ->
timer:sleep(1000),
exit(unexpected_failure)
end),
receive
{'EXIT', Child, Reason} ->
io:format("Child ~p exited: ~p~n", [Child, Reason])
end.
trapping_parent() ->
process_flag(trap_exit, true),
{Pid, Ref} = spawn_monitor(fun() -> 1/0 end),
receive
{'DOWN', Ref, process, Pid, Reason} ->
io:format("Monitored process ~p went down: ~p~n", [Pid, Reason])
end.
trap_exit: Turning Crashes into Messages
Calling process_flag(trap_exit, true) changes how a process handles incoming exit signals from its links: instead of being killed by them, the process receives them as ordinary {'EXIT', Pid, Reason} tuples delivered to its mailbox, which it can then pattern-match on inside a normal receive. This is the exact mechanism OTP's supervisor behaviour is built on — a supervisor is, at its core, a process that links to its children and traps their exits so it can react programmatically instead of dying alongside them.
Cricket analogy: A vice-captain designated to formally receive and log every injury report from the physio, rather than being knocked out of the game themselves, mirrors process_flag(trap_exit, true) converting a lethal exit signal into a harmless message the process can inspect.
A process created with plain spawn (no link, no monitor) is completely invisible to failure detection — if it crashes, nothing else in the system is notified. This is a common source of silently 'lost' processes in early Erlang code; prefer spawn_link or spawn_monitor unless true fire-and-forget isolation is intended.
monitor vs link: Choosing the Right Tool
monitor/2 (or the atomic spawn_monitor/1,3) sets up a unidirectional watch on a process: the monitoring process is notified with a {'DOWN', Ref, process, Pid, Reason} message when the monitored process terminates, for any reason, but the monitoring process itself is never killed as a side effect. This makes monitor the safer choice when you simply need to know that something finished or crashed — for example, to time out a request or clean up a resource — without accepting the bidirectional, potentially lethal coupling that a link creates.
Cricket analogy: A team analyst watching a rival team's player performance stats without being on their playing roster is a one-way relationship — the analyst's own game isn't affected by the rival player's dismissal, just as monitor/2 gives notification without the lethal, bidirectional tie of a link.
Use spawn_monitor (or monitor/2 on an existing Pid) when you need to know a process died — for example, to reply to a waiting caller with an error — but you must not risk your own process being killed as a side effect. Reserve link/spawn_link for cases where the two processes' lifetimes should genuinely be tied together, such as a supervisor and its child.
- spawn/1,3 creates a new process and immediately returns its Pid, with no default supervision relationship.
- spawn_link/1,3 atomically creates and links a process, avoiding a race condition present in separate spawn+link calls.
- Links are bidirectional: an abnormal exit on either linked process propagates an exit signal to the other.
- By default, receiving a non-normal exit signal terminates the receiving process too.
- process_flag(trap_exit, true) converts incoming exit signals into ordinary {'EXIT', Pid, Reason} messages.
- monitor/2 (or spawn_monitor) creates a unidirectional, non-lethal notification via a 'DOWN' message.
- Supervisors are built on top of spawn_link and trap_exit.
Practice what you learned
1. What is the key difference between spawn and spawn_link?
2. By default, what happens to a linked process when its partner exits with reason `some_error`?
3. What does process_flag(trap_exit, true) do?
4. How does monitor/2 differ from link/1?
5. What message does a monitoring process receive when the monitored process terminates?
Was this page helpful?
You May Also Like
Processes and Message Passing
Learn how Erlang's lightweight processes communicate exclusively through asynchronous message passing, forming the foundation of concurrent, fault-tolerant systems.
Supervisors Explained
Learn how OTP supervisors use child specifications and restart strategies to automatically detect and recover from process failures.
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