erlang-distribution
Handles distributed Erlang processes, node communication, and fault tolerance on the BEAM VM.
Install
mkdir -p .claude/skills/erlang-distribution && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/4399" && unzip -o skill.zip -d .claude/skills/erlang-distribution && rm skill.zipInstalls to .claude/skills/erlang-distribution
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Use when erlang distributed systems including node connectivity, distributed processes, global name registration, distributed supervision, network partitions, and building fault-tolerant multi-node applications on the BEAM VM.Key capabilities
- →Manage node connectivity
- →Implement distributed supervision
- →Register global process names
- →Handle network partitions
How it works
The skill provides patterns for building clustered, fault-tolerant systems using Erlang's built-in distribution layer.
Inputs & outputs
When to use erlang-distribution
- →Design fault-tolerant distributed applications
- →Implement global process registries
- →Troubleshoot BEAM node connectivity
- →Configure distributed supervision trees
About this skill
Erlang Distribution
Introduction
Erlang's built-in distribution enables building clustered, fault-tolerant systems across multiple nodes. Processes on different nodes communicate transparently through the same message-passing primitives used locally. This location transparency makes distributed programming natural and straightforward.
The distribution layer handles network communication, serialization, and node connectivity automatically. Nodes discover each other through naming, with processes addressable globally via registered names or pid references. Understanding distribution patterns is essential for building scalable, resilient systems.
This skill covers node connectivity and clustering, distributed message passing, global name registration, distributed supervision, handling network partitions, RPC patterns, and building production distributed applications.
Node Connectivity
Nodes connect to form clusters for distributed computation and fault tolerance.
%% Starting named nodes
%% erl -name node1@hostname -setcookie secret
%% erl -sname node2 -setcookie secret
%% Connecting nodes
connect_nodes() ->
Node1 = 'node1@host',
Node2 = 'node2@host',
net_kernel:connect_node(Node2).
%% Check connected nodes
list_nodes() ->
Nodes = [node() | nodes()],
io:format("Connected nodes: ~p~n", [Nodes]).
%% Monitor node connections
monitor_nodes() ->
net_kernel:monitor_nodes(true),
receive
{nodeup, Node} ->
io:format("Node up: ~p~n", [Node]);
{nodedown, Node} ->
io:format("Node down: ~p~n", [Node])
end.
%% Node configuration
start_distributed() ->
{ok, _} = net_kernel:start([mynode, shortnames]),
erlang:set_cookie(node(), secret_cookie).
%% Hidden nodes (for monitoring)
connect_hidden(Node) ->
net_kernel:connect_node(Node),
erlang:disconnect_node(Node),
net_kernel:hidden_connect_node(Node).
%% Get node information
node_info() ->
#{
name => node(),
cookie => erlang:get_cookie(),
nodes => nodes(),
alive => is_alive()
}.
Node connectivity enables building distributed clusters with automatic discovery.
Distributed Message Passing
Send messages to processes on remote nodes using same syntax as local messaging.
%% Send to registered process on remote node
send_remote(Node, Name, Message) ->
{Name, Node} ! Message.
%% Spawn process on remote node
spawn_on_remote(Node, Fun) ->
spawn(Node, Fun).
spawn_on_remote(Node, Module, Function, Args) ->
spawn(Node, Module, Function, Args).
%% Distributed request-response
remote_call(Node, Module, Function, Args) ->
Pid = spawn(Node, fun() ->
Result = apply(Module, Function, Args),
receive
{From, Ref} -> From ! {Ref, Result}
end
end),
Ref = make_ref(),
Pid ! {self(), Ref},
receive
{Ref, Result} -> {ok, Result}
after 5000 ->
{error, timeout}
end.
%% Distributed work distribution
-module(work_dispatcher).
-export([start/0, dispatch/1]).
start() ->
register(?MODULE, spawn(fun() -> loop([]) end)).
dispatch(Work) ->
?MODULE ! {dispatch, Work}.
loop(Workers) ->
receive
{dispatch, Work} ->
Node = select_node(nodes()),
Pid = spawn(Node, fun() -> do_work(Work) end),
loop([{Pid, Node} | Workers])
end.
select_node(Nodes) ->
lists:nth(rand:uniform(length(Nodes)), Nodes).
do_work(Work) ->
Result = process_work(Work),
io:format("Work done on ~p: ~p~n", [node(), Result]).
process_work(Work) -> Work * 2.
%% Remote group leader for output
remote_process_with_io(Node) ->
spawn(Node, fun() ->
group_leader(self(), self()),
io:format("Output from ~p~n", [node()])
end).
Location-transparent messaging enables seamless distributed communication.
Global Name Registration
Register process names globally across distributed clusters.
%% Global registration
register_global(Name) ->
Pid = spawn(fun() -> global_loop() end),
global:register_name(Name, Pid),
Pid.
global_loop() ->
receive
{From, Message} ->
From ! {reply, Message},
global_loop();
stop -> ok
end.
%% Send to globally registered process
send_global(Name, Message) ->
case global:whereis_name(Name) of
undefined ->
{error, not_found};
Pid ->
Pid ! Message,
ok
end.
%% Global name with conflict resolution
register_with_resolve(Name) ->
Pid = spawn(fun() -> server_loop() end),
ResolveFun = fun(Name, Pid1, Pid2) ->
%% Keep process on node with lower name
case node(Pid1) < node(Pid2) of
true -> Pid1;
false -> Pid2
end
end,
global:register_name(Name, Pid, ResolveFun).
server_loop() ->
receive
Message ->
io:format("Received: ~p on ~p~n", [Message, node()]),
server_loop()
end.
%% Global synchronization
sync_global() ->
global:sync().
%% List globally registered names
list_global_names() ->
global:registered_names().
%% Re-register after node reconnection
ensure_global_registration(Name, Fun) ->
case global:whereis_name(Name) of
undefined ->
Pid = spawn(Fun),
global:register_name(Name, Pid),
Pid;
Pid ->
Pid
end.
Global registration enables location-independent process discovery.
Distributed Supervision
Supervise processes across multiple nodes for cluster-wide fault tolerance.
-module(distributed_supervisor).
-behaviour(supervisor).
-export([start_link/0, start_worker/1]).
-export([init/1]).
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
start_worker(Node) ->
ChildSpec = #{
id => make_ref(),
start => {worker, start_link, [Node]},
restart => permanent,
type => worker
},
supervisor:start_child(?MODULE, ChildSpec).
init([]) ->
SupFlags = #{
strategy => one_for_one,
intensity => 5,
period => 60
},
{ok, {SupFlags, []}}.
%% Worker module spawning on specific node
-module(worker).
-export([start_link/1, loop/0]).
start_link(Node) ->
Pid = spawn_link(Node, ?MODULE, loop, []),
{ok, Pid}.
loop() ->
receive
stop -> ok;
Msg ->
io:format("Worker on ~p: ~p~n", [node(), Msg]),
loop()
end.
%% Distributed process groups
-module(pg_example).
-export([start/0, join/1, broadcast/1]).
start() ->
pg:start_link().
join(Group) ->
pg:join(Group, self()).
broadcast(Group, Message) ->
Members = pg:get_members(Group),
[Pid ! Message || Pid <- Members].
Distributed supervision maintains system health across node failures.
RPC and Remote Execution
Execute function calls on remote nodes with various invocation patterns.
%% Basic RPC
simple_rpc(Node, Module, Function, Args) ->
rpc:call(Node, Module, Function, Args).
%% RPC with timeout
timed_rpc(Node, Module, Function, Args, Timeout) ->
rpc:call(Node, Module, Function, Args, Timeout).
%% Async RPC
async_rpc(Node, Module, Function, Args) ->
Key = rpc:async_call(Node, Module, Function, Args),
%% Later retrieve result
rpc:yield(Key).
%% Parallel RPC to multiple nodes
parallel_rpc(Nodes, Module, Function, Args) ->
rpc:multicall(Nodes, Module, Function, Args).
%% Parallel call with results
parallel_rpc_results(Nodes, Module, Function, Args) ->
rpc:multicall(Nodes, Module, Function, Args, 5000).
%% Cast (fire and forget)
cast_rpc(Node, Module, Function, Args) ->
rpc:cast(Node, Module, Function, Args).
%% Broadcast to all nodes
broadcast_rpc(Module, Function, Args) ->
Nodes = [node() | nodes()],
rpc:multicall(Nodes, Module, Function, Args).
%% Parallel map over nodes
pmap_nodes(Fun, List) ->
Nodes = nodes(),
DistFun = fun(X) ->
Node = lists:nth((X rem length(Nodes)) + 1, Nodes),
rpc:call(Node, erlang, apply, [Fun, [X]])
end,
lists:map(DistFun, List).
RPC enables convenient remote execution with location transparency.
Network Partitions and CAP
Handle network partitions and understand CAP theorem trade-offs.
%% Detect network partition
detect_partition() ->
ExpectedNodes = [node1@host, node2@host, node3@host],
CurrentNodes = nodes(),
Missing = ExpectedNodes -- CurrentNodes,
case Missing of
[] -> ok;
Nodes -> {partition, Nodes}
end.
%% Partition healing strategy
-module(partition_handler).
-export([monitor_cluster/1]).
monitor_cluster(ExpectedNodes) ->
net_kernel:monitor_nodes(true),
monitor_loop(ExpectedNodes, nodes()).
monitor_loop(Expected, Current) ->
receive
{nodeup, Node} ->
NewCurrent = [Node | Current],
case length(NewCurrent) == length(Expected) of
true ->
io:format("Cluster fully connected~n"),
heal_partition();
false ->
ok
end,
monitor_loop(Expected, NewCurrent);
{nodedown, Node} ->
NewCurrent = lists:delete(Node, Current),
io:format("Partition detected: ~p~n", [Node]),
monitor_loop(Expected, NewCurrent)
end.
heal_partition() ->
%% Synchronize state after partition heals
global:sync(),
ok.
%% Consensus with majority
-module(consensus).
-export([propose/2, vote/3]).
propose(Nodes, Value) ->
Ref = make_ref(),
[Node ! {vote, self(), Ref, Value} || Node <- Nodes],
collect_votes(Ref, length(Nodes), 0).
collect_votes(_Ref, Total, Votes) when Votes > Total div 2 ->
{ok, majority};
collect_votes(_Ref, Total, Total) ->
{error, no_majority};
collect_votes(Ref, Total, Votes) ->
receive
{vote, Ref, accept} ->
collect_votes(Ref, Total, V
---
*Content truncated.*
When not to use it
- →Single-node applications without distribution needs
Prerequisites
Limitations
- →Requires careful handling of network partitions
- →Global registry can become a bottleneck
How it compares
It offers specific patterns for distributed Erlang nodes rather than generic distributed system design.
Compared to similar skills
erlang-distribution side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| erlang-distribution (this skill) | 1 | 6mo | No flags | Advanced |
| architecture-patterns | 55 | 2mo | No flags | Advanced |
| kotlin-multiplatform | 32 | 3mo | Review | Advanced |
| nodejs-best-practices | 28 | 6mo | No flags | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by benchflow-ai
View all by benchflow-ai →You might also like
architecture-patterns
wshobson
Implement proven backend architecture patterns including Clean Architecture, Hexagonal Architecture, and Domain-Driven Design. Use when architecting complex backend systems or refactoring existing applications for better maintainability.
kotlin-multiplatform
vitorpamplona
Platform abstraction decision-making for Amethyst KMP project. Guides when to abstract vs keep platform-specific, source set placement (commonMain, jvmAndroid, platform-specific), expect/actual patterns. Covers primary targets (Android, JVM/Desktop, iOS) with web/wasm future considerations. Integrates with gradle-expert for dependency issues. Triggers on: abstraction decisions ("should I share this?"), source set placement questions, expect/actual creation, build.gradle.kts work, incorrect placement detection, KMP dependency suggestions.
nodejs-best-practices
davila7
Node.js development principles and decision-making. Framework selection, async patterns, security, and architecture. Teaches thinking, not copying.
workflow-orchestration-patterns
wshobson
Design durable workflows with Temporal for distributed systems. Covers workflow vs activity separation, saga patterns, state management, and determinism constraints. Use when building long-running processes, distributed transactions, or microservice orchestration.
java-pro
sickn33
Master Java 21+ with modern features like virtual threads, pattern matching, and Spring Boot 3.x. Expert in the latest Java ecosystem including GraalVM, Project Loom, and cloud-native patterns. Use PROACTIVELY for Java development, microservices architecture, or performance optimization.
arm-cortex-expert
sickn33
Senior embedded software engineer specializing in firmware and driver development for ARM Cortex-M microcontrollers (Teensy, STM32, nRF52, SAMD). Decades of experience writing reliable, optimized, and maintainable embedded code with deep expertise in memory barriers, DMA/cache coherency, interrupt-driven I/O, and peripheral drivers.