Lessons

Every module combines a model, a rule, an example, and a challenge.

That is how understanding replaces memorization.

Feedback Loop

Make progress visible while you learn.

The page now rewards effort, not just perfect answers. Write notes, solve drills, and build momentum.

XP

0 XP

Start with one lesson note or one code drill to unlock your first progress signal.

FOCUS

Best next move

Open a module, write one thought in the note field, then run one coding drill.

PRACTICE

0 notes, 0 drills

0 quiz wins and 0 checked milestones completed.

Lessons

Every module combines a model, a rule, an example, and a challenge.

That is how understanding replaces memorization.

Module 1

Syntax and data types

Module goal

Build a reliable mental model for Erlang values, names, and pattern matching.

You will be able to
  • identify atoms, tuples, and binaries by shape
  • read bindings from left to right without guessing
  • predict when a pattern match will fail
Step 1

Lesson 1: Atoms, numbers, strings

Erlang clearly separates atoms like ok, numbers like 42, and binaries like <<"hi">>.

Step 2

Lesson 2: Pattern matching

Pattern matching is not just comparison. It is structured unpacking of values.

Step 3

Guided build

Name three values with different shapes and read them back aloud.

Then match one success tuple and one error tuple until the left-hand pattern feels natural.

Checkpoint

If you can explain why {ok, User} = Value may fail, you are ready for the next module.

Lesson 1: Atoms, numbers, strings

Erlang clearly separates atoms like ok, numbers like 42, and binaries like <<"hi">>.

Memory line: An atom often describes meaning, a binary often carries actual data.

State = idle,
Count = 3,
Name = <<"Ada">>.

Lesson 2: Pattern matching

Pattern matching is not just comparison. It is structured unpacking of values.

Memory line: Erlang always asks, Does the shape fit?

{ok, User} = {ok, #{name => <<"Ada">>}}.
Mini challenge

Which parts of {error, timeout} can you extract directly with pattern matching?

Practice lab

No feedback yet.

Module 2

Functions, guards, and recursion

Module goal

Move from static values into executable rules and recursive thinking.

You will be able to
  • choose the correct function head for the input shape
  • write a base case before the recursive step
  • explain why recursion stops instead of looping forever
Step 1

Lesson 3: Multiple function heads

A function can have multiple shapes. Erlang checks them from top to bottom.

Step 2

Lesson 4: Guards

Guards make rules readable and keep logic out of the body when possible.

Step 3

Guided build

Start every recursive function by writing the empty or simple case first.

Then add the [H | T] case and say what becomes smaller on each call.

Checkpoint

If you can sketch sum/1 and explain why it stops, recursion is starting to click.

Lesson 3: Multiple function heads

A function can have multiple shapes. Erlang checks them from top to bottom.

Memory line: First pattern, then guard, then function body.

size([]) -> 0;
size([_ | Tail]) -> 1 + size(Tail).

Lesson 4: Guards

Guards make rules readable and keep logic out of the body when possible.

Memory line: Guards clarify cases before work begins.

kind(N) when N > 0 -> positive;
kind(0) -> zero;
kind(_) -> negative.

Lesson 5: Recursion instead of loops

In Erlang, recursion is the normal way to move through data.

Memory line: Every recursion needs a start, a step, and an end.

sum([]) -> 0;
sum([H | T]) -> H + sum(T).
Mini challenge

Mentally design a function all_even/1 that returns true only if every element is even.

Practice lab

No feedback yet.

Module 3

Processes and message passing

Module goal

Think in processes, mailboxes, and explicit message protocols instead of shared state.

You will be able to
  • explain what state a process owns
  • design message shapes for change and read requests
  • turn a protocol into a receive loop
Step 1

Lesson 6: Starting processes

An Erlang process is extremely lightweight and owns its own state.

Step 2

Lesson 7: Sending messages

With !, you send messages asynchronously into a process mailbox.

Step 3

Guided build

Write the message format before writing the receive block.

For each branch, decide whether state changes, a reply is sent, or both.

Checkpoint

If you can describe increment and {get, From} as a protocol, you are learning the Erlang way.

Lesson 6: Starting processes

An Erlang process is extremely lightweight and owns its own state.

Memory line: Do not share state, send messages.

Pid = spawn(fun loop/0).

Lesson 7: Sending messages

With !, you send messages asynchronously into a process mailbox.

Memory line: Sending is immediate, processing comes later.

Pid ! {self(), ping}.

Lesson 8: Receive loops

A process is often modeled as a loop: receive a message, react, continue.

Memory line: Behavior emerges from receiving plus the next loop.

receive
    stop -> ok;
    Msg -> io:format("~p~n", [Msg]), loop()
end.
Mini challenge

How would you design a counter process that reacts to increment and get?

Practice lab

No feedback yet.

Module 4

OTP and fault tolerance

Module goal

Understand why OTP turns raw processes into production-ready building blocks.

You will be able to
  • explain what handle_call is responsible for
  • separate worker logic from supervision logic
  • choose a basic supervision strategy with a reason
Step 1

Lesson 9: Let it crash

In Erlang, error handling is often structural: one process may crash while another restores it.

Step 2

Lesson 10: GenServer thinking

GenServer encapsulates state and standardizes the message flow.

Step 3

Guided build

Say which part belongs to the worker and which part belongs to supervision.

Then map a simple request into handle_call plus a reply tuple.

Checkpoint

If you can justify one_for_one in plain language, you are past the syntax stage.

Lesson 9: Let it crash

In Erlang, error handling is often structural: one process may crash while another restores it.

Memory line: Not every error should be fixed inside the same process.

link(WorkerPid).

Lesson 10: GenServer thinking

GenServer encapsulates state and standardizes the message flow.

Memory line: OTP gives you structure for repeating process patterns.

handle_call(get, _From, State) ->
    {reply, State, State}.

Lesson 11: Supervisors

Supervisors decide whether a single worker or an entire group should restart.

Memory line: Resilience is a tree structure, not an accident.

{one_for_one, 5, 10}
Mini challenge

When would a one_for_one strategy make more sense than one_for_all?

Practice lab

No feedback yet.

Module 5

Concurrency patterns

Module goal

Use isolation and message flow to structure concurrent work cleanly.

You will be able to
  • decide which process owns which state
  • split a pipeline into focused stages
  • protect shared data by turning it into a protocol
Step 1

Lesson 12: Worker pools

Multiple processes can handle the same kind of task in parallel without blocking one another.

Step 2

Lesson 13: Isolating state

State should ideally live inside a single process and never be shared directly.

Step 3

Guided build

Choose exactly one process that owns the map or queue.

Then define which messages enter, which replies leave, and where validation happens.

Checkpoint

If each process has one job and one state boundary, your design is getting professional.

Lesson 12: Worker pools

Multiple processes can handle the same kind of task in parallel without blocking one another.

Memory line: Parallelism needs work distribution, not just more CPU.

Workers = [spawn(fun worker/0) || _ <- lists:seq(1, 4)].

Lesson 13: Isolating state

State should ideally live inside a single process and never be shared directly.

Memory line: Isolation reduces side effects.

store_loop(State) ->
    receive
        {put, Key, Val} -> store_loop(maps:put(Key, Val, State));
        {get, From, Key} -> From ! maps:get(Key, State), store_loop(State)
    end.
Mini challenge

Sketch a three-step pipeline with one process for receiving, one for validating, and one for storing.

Practice lab

No feedback yet.

Module 6

Distributed Erlang

Module goal

Add failure-aware thinking once messages cross machine boundaries.

You will be able to
  • reason about timeout and retry as part of the API
  • separate success path from network failure path
  • treat distribution as a design problem, not magic
Step 1

Lesson 14: Nodes

A node is a running Erlang instance that can cooperate with other nodes.

Step 2

Lesson 15: Remote messaging

Messages can cross nodes as long as naming and connectivity are correct.

Step 3

Guided build

Write the success path first, then add the timeout branch immediately.

Decide what the caller should do after timeout: retry, log, or escalate.

Checkpoint

If timeout is part of your first draft, you are starting to think like a distributed systems engineer.

Lesson 14: Nodes

A node is a running Erlang instance that can cooperate with other nodes.

Memory line: Distribution starts with explicit connection, not magic.

net_kernel:connect_node('worker@host').

Lesson 15: Remote messaging

Messages can cross nodes as long as naming and connectivity are correct.

Memory line: A distributed system is only as good as its failure assumptions.

{service, 'worker@host'} ! ping.

Lesson 16: Production thinking

In distributed systems, timeouts, retries, monitoring, and ownership matter.

Memory line: Strong systems plan for network failure from the start.

receive
    reply -> ok
after 2000 ->
    timeout
end.
Mini challenge

What kinds of failures can happen when a remote node is temporarily unreachable?

Practice lab

No feedback yet.

Practice Studio

Write Erlang yourself and get instant feedback.

These drills are lightweight browser checks, not a full compiler, but they push learners into active construction instead of only reading.

Drill 1

Pattern Match a Success Tuple

Write one Erlang line that extracts User from a value shaped like {ok, #{name => <<"Ada">>}}.

No feedback yet.

Drill 2

Recursive Sum Function

Write a recursive sum/1 function with a base case for [] and a recursive step for [H | T].

No feedback yet.

Drill 3

Mailbox Counter Loop

Sketch a process loop that handles an increment message and a get message that replies back to From.

No feedback yet.

Account

Login, register, and save your progress.

Account

Login, register, and save your progress.