Learn distributed systems by building them from first principles using raw Elixir process primitives.
This repository is a collection of small, self-contained, runnable examples that demonstrate the building blocks of distributed systems on the BEAM.
The goal is not to learn Phoenix or build CRUD applications.
Instead, the focus is understanding how distributed systems are constructed from the ground up before introducing OTP abstractions such as GenServer, Supervisor, Registry, or distributed libraries.
Every example can be executed independently, explained in detail, and paired with a technical blog post.
Each project follows the same approach:
- Explain the problem.
- Design a minimal protocol.
- Implement it using raw Elixir primitives.
- Explain every message exchanged.
- Discuss limitations.
- Show how OTP solves those limitations.
The intention is to understand why an abstraction exists before using it.
elixir-distributed-systems-lab/
│
├── 01-building-a-stateful-process-in-elixir-without-genserver/
├── 02-request-reply/
├── 03-process-monitoring/
├── ...
└── README.md
Each example contains:
README.md
example.exs
Every example is:
- Runnable with a single command
- Self-contained
- Minimal
- Focused on one concept
- Documented with diagrams
- Blog-ready
-
Building a Stateful Process in Elixir Without GenServer
-
spawn/1 -
Process state
-
Mailboxes
-
send -
receive -
Request–reply protocol
-
Blog post: Building a Stateful Process in Elixir Without GenServer
-
-
02 - Correlated Request Reply
-
make_ref/0 -
Request IDs
-
Matching replies
-
Concurrent clients
-
Blog post: Correlated request–reply in Elixir
-
-
03 - Process Monitoring
-
Process.monitor/1 -
Detecting process termination
-
DOWN messages
-
Blog post: Process monitoring in Elixir
-
-
04 - Process Linking
-
spawn_link/1 -
Exit propagation
-
Linked processes
-
Blog post: Process linking in Elixir
-
-
05 - Supervisor From Scratch
-
Manual restart loop
-
One-for-one restart strategy
-
Why supervisors exist
-
Blog post: Supervisor from scratch
-
-
06 - Named Processes
-
Process registration
-
Global lookup
-
Avoiding PID sharing
-
Blog post: Named processes
-
-
07 - Worker Pool
-
Task distribution
-
Multiple workers
-
Load balancing
-
Blog post: Worker Pool
-
-
08 - Publish / Subscribe
- Multiple subscribers
- Broadcast messaging
-
09 - Backpressure
- Fast producers
- Slow consumers
- Mailbox growth
-
10 - Connecting Nodes
Node.connect/1- Distributed Erlang
-
11 - Remote Message Passing
- Sending messages across nodes
-
12 - Detecting Node Failures
Node.monitor/2- Network partitions
-
13 - Distributed Counter
- State replication
- Consistency challenges
-
14 - Primary / Replica
- Single writer
- Replication protocol
-
15 - Heartbeats
- Failure detection
- Liveness
-
16 - Leader Election
- Choosing a coordinator
- Split-brain discussion
-
17 - Minimal Job Queue
- Job scheduling
- Worker retries
- Failed jobs
-
18 - Reliable Messaging
- ACK protocol
- Retries
- Duplicate handling
-
19 - Write Ahead Log
- Crash recovery
- Persistent messages
-
20 - Distributed Key-Value Store
- Replicated state
- Request routing
-
21 - G-Counter (CRDT)
- Eventual consistency
- Merge operations
- 22 - Tiny Distributed Message Queue
A minimal distributed queue built entirely from concepts introduced in previous examples.
Features include:
- Multiple nodes
- Worker processes
- Reliable delivery
- Job retries
- Monitoring
- Supervision
- Persistence
- Failure recovery
Developers interested in:
- Distributed systems
- Erlang/OTP
- Elixir internals
- RabbitMQ concepts
- Fault tolerance
- Message passing
- Concurrent programming
- BEAM architecture
cd 01-building-a-stateful-process-in-elixir-without-genserver
elixir building_a_stateful_process_in_elixir_without_genserver.exsEach example is completely independent and can be studied in any order, although following the roadmap is recommended.
Each project in this repository is accompanied by a technical article explaining:
- The real-world problem
- Design decisions
- Protocol diagrams
- Message flow
- Failure cases
- Trade-offs
- Relationship to OTP abstractions
The source code in this repository is licensed under the MIT License.
The written articles in each blog.md file are licensed under Creative Commons Attribution-NonCommercial 4.0 International. You may share and adapt that content with attribution, but not for commercial purposes.