Typed distributed messaging for Gleam on the BEAM.
distribute is a thin typed safety layer over Erlang's distribution
primitives. It puts binary codecs in front of :global and Subject so
the compiler catches protocol mismatches before messages leave the
process. Payload size and dead-target detection are enforced at every
I/O boundary, so a misbehaving peer cannot OOM your node or hang it.
gleam add distributeRequires Gleam 1.16 or newer, Erlang target only.
import distribute
import distribute/codec
import distribute/receiver
let greeter = distribute.named("greeter", codec.string())
let assert Ok(_gs) =
distribute.start_registered(greeter, Nil, fn(msg, _state) {
io.println("got: " <> msg)
receiver.Continue(Nil)
})
let assert Ok(target) = distribute.lookup(greeter)
let assert Ok(Nil) = distribute.send(target, "hello")For the full walkthrough see docs/quickstart.md.
All long-form docs live in docs/:
- Quickstart. Boot, configure, send.
- Recipes. Counter, pool, versioned protocol, cluster events, custom records.
- Actors and registry.
- Messaging.
send/receive/call. - Codecs and types. Wire format, custom records, tagged messages.
- Safety and limits. Payload limits, threat model, recommended sizing.
- Typed boundary.
TypedName(msg)binds a name to a codec. Registration and lookup share the samemsgtype, and the compiler rejects mismatches. - Hard payload caps.
max_payload_size_bytesis enforced before encode and before decode on every path:send,receive,call,reply, actor handlers, selectors. - Fast-fail calls.
global.callmonitors the target. A dead target returnsError(TargetDown)immediately. Late replies and DOWN messages are drained from the caller's mailbox. - OTP-native. Real OTP gen_server-flavored actors via
gleam_otp/actor, real supervisors, real child specs.observer,sys:get_status, restart strategies all work. No magic. - Single-source codec. Encoding and decoding happen through one
Codec(a)value. Combinators (map,list,option,tuple,tagged) cover the common cases without macros.
Seamlessly encode and decode your Algebraic Data Types (enums) with a fluent builder.
pub type MyMessage {
Text(String)
Ping
}
import distribute/codec
import distribute/codec/variant
let my_codec =
variant.new()
|> variant.add(0, "Text", codec.string(), Text, fn(m) {
case m { Text(s) -> Ok(s); _ -> Error(Nil) }
})
|> variant.unit(1, "Ping", Ping, fn(m) { m == Ping })
|> variant.build()Subscribe to cluster events (NodeUp, NodeDown) to react to node topology changes.
import distribute
import distribute/cluster/monitor
let subj = process.new_subject()
let assert Ok(m) = distribute.subscribe(subj)
// In your actor/process
case process.receive(subj, 5000) {
Ok(monitor.NodeUp(node)) -> io.println("Node joined: " <> node)
Ok(monitor.NodeDown(node)) -> io.println("Node left: " <> node)
_ -> Nil
}
// Later
distribute.unsubscribe(m)- Two codebases, one wire.
TypedNameenforces type safety inside one codebase. Mismatched codecs across separate codebases produce runtime decode errors, not compile errors. - No auto-derive. Gleam has no macros, so complex codecs are manual. The combinators keep them short.
terminatecaveat ingleam_otp/actor1.x. External shutdown paths do not currently invoke an OTP-styleterminatecallback. If an actor owns files, sockets, ETS tables, ports, or other external resources, use the linked resource-owner pattern documented in docs/recipes.md and docs/safety_and_limits.md.- One internal coupling. We construct
Subjectfrom a remote PID via one Erlang FFI function. That is the single point that depends ongleam_erlang's subject layout.
epmd -daemon # enable real-peer tests
gleam test # unavailable peer prerequisites print SKIP locally
DISTRIBUTE_REQUIRE_MULTINODE=1 gleam test # require real-peer coverage (CI default)
gleam dev # multi-node playground
gleam docs build # local API docsCI fails if real-peer prerequisites are unavailable. Local runs report the test and reason on stderr when distribution or peer startup is unavailable. Once peers are running, connection, registration and synchronization failures fail the test in every mode.
CI covers Gleam 1.16.0 / OTP 27.0 and Gleam 1.19.2 / OTP 29.1.2. Formatting and documentation checks run on the newer toolchain. Action revisions are pinned and updated manually.
MIT. See LICENSE.
