Course

Erlang — The Complete Course

The BEAM, immutability, pattern matching, concurrency via processes, OTP, and supervision — the language behind telecom-grade fault tolerance.

Language course · 6 units

Unit 1: Unit 1 — Values, immutability & pattern matching

Erlang is a functional language: data is immutable, every value is an expression, and functions are pure. Pattern matching IS the assignment — you bind by matching a term against a pattern, which also does the equality and destructuring in one step.

Teach: '=' is a match, not an assignment

X = 5 binds X to 5. 5 = 5 matches (both are 5, success). 6 = 5 fails with a badmatch — this is how you write assertions and destructure. {A, [H | _]} = {ok, [1,2,3]} binds A=ok, H=1. There is no mutation; 'reassignment' is rebinding in a new scope.

Exercises

Practice problems

Unit 2: Unit 2 — Processes, messages & the BEAM scheduler

Concurrency is the language's core: every unit of work is a lightweight process (not an OS thread) managed by the BEAM scheduler, with NO shared state — processes communicate only by copying messages to mailboxes. This gives the 'isolation + fast context switch' foundation for OTP.

Teach: actor model in one example

Pid = spawn(fun() -> receive {ping, From} -> From ! pong end end). Pid ! {ping, self()}. wait: receive pong -> ok end. spawn returns a Pid you can message; each process owns a mailbox. The message copy means no locks, no shared-memory races — a genuine advantage for fault isolation: a crashing process cannot corrupt a sibling's state.

Exercises

Practice problems

Unit 3: Unit 3 — OTP: GenServer, supervision, fault tolerance

OTP turns the raw receive loop into reusable behaviours. gen_server gives call/cast/info + a clean state; a supervisor monitors children and restarts them with a configured strategy; a supervision tree is the 'let it crash' architecture. This is what makes Erlang systems self-healing.

Teach: a GenServer counter

gen_server:start_link -> init(Cnt) -> {ok, Cnt}. handle_call(inc, _From, S) -> {reply, S+1, S+1}. Call: gen_server:call(Pid, inc). The state is threaded through handle_*; a crash in the callback does not corrupt the caller — the supervisor restarts the child with its init. State is per-process, isolated and safe.

Exercises

Practice problems

Unit 4: Unit 4 — ETS, distributions & systems thinking

ETS gives in-memory, concurrent, shared (per-process-owned) tables with bag/ordered_set semantics and fast lookups; distributed Erlang spans nodes, but the 'share nothing' message model stays the same. Interviewers value the fallen-over engineering view: design for failure, backpressure, and supervision.

Teach: ETS for a shared cache

Create ETS owned by a process: ets:new(cache, [named_table, public, set, {read_concurrency,true}]). Writes go through the owner; reads can be concurrent. Because ownership is per-process, the table dies with its owner — tying the table lifetime to a supervised process gives you clean restart semantics.

Exercises

Practice problems

Unit 5: Unit 5 — Immutability & pattern matching

Erlang data is immutable — you never mutate, you rebind and build new values. This is what makes concurrency safe and what makes recursion the default loop. Pattern matching is the heart of the language: it destructures and guards in one step. Master = (match), guards (when), head/tail list recursion, and list comprehensions. Every interview answer should show immutable, recursive, pattern-matched code.

Teach: recursion is the loop

There is no for/while; you recurse. The canonical shape: a base case and a recursive case that consumes the head and recurses on the tail, often carrying an accumulator for tail-call optimization. Example — sum: sum([]) -> 0; sum([H|T]) -> H + sum(T). The BEAM optimizes tail calls, so a tail-recursive accumulator version runs in constant stack. Pattern matching destructures: {ok, Val} = Result binds Val only if the tuple matches.

Exercises

Practice problems

Unit 6: Unit 6 — Supervision trees & fault tolerance

Erlang's fault-tolerance model is 'let it crash': a process that hits an unexpected state dies fast, and its supervisor restarts it from a known-good state. A supervision tree is a hierarchy of supervisors and workers with explicit restart strategies (one_for_one, one_for_all, rest_for_one) and intensity/period limits. This is why Erlang systems survive faults — the recovery is structural, not exception-handling.

Teach: why 'let it crash' is safe

A worker owns a narrow job; if it hits an impossible state, it exits abnormally. The supervisor sees the exit, and per its strategy restarts the worker (one_for_one) or siblings (one_for_all/rest_for_one) within intensity/period. Because state is rebuilt from scratch, there is no corrupt half-state to clean. This trades a rare crash for guaranteed recovery — the opposite of catching everything and limping along.

Exercises

Practice problems

Open this course in Dojo