Information Density: Erlang/OTP – Signal Evidence & AI Readability

Erlang/OTP

(https://erlang.org) 📸 Data Snapshot: May 30, 2026
Information Density — The Lens

Classify each sentence as substantive or hollow. Grounding markers — numbers, currencies, dates, technical units, named entities — outweigh marketing adjectives. When fluff sits right next to hard evidence, the fluff is forgiven.

Info Density Power-words vs. Substance ratio.
28 Impact Weight: 30 / 100
93% Reputation

Information density is exceptionally high. Body text across all pages avoids generic marketing language in favor of technical protocols, such as the literal shell command ./configure && make && make install on the downloads page. Headings like ‘Supervision Trees’ and ‘Behaviours’ lead directly into dense technical explanations and Erlang code snippets rather than power-word-heavy sales pitches.

Information Density is read straight from the body copy: how much of the text carries grounded, checkable substance versus hollow filler. Below is the clean text the engine analyzed, then the industry’s known generic-claim patterns to weigh it against.

📝 The Narrative — clean text per page (the substance-vs-filler signal)
HOMEPAGE (https://erlang.org) Index – Erlang/OTP
[H2] What is Erlang?
Erlang is a programming language used to build massively scalable soft real-time
systems with requirements on high availability. Some of its uses are in telecoms, banking,
e-commerce, computer telephony and instant messaging. Erlang's runtime system has built-in
support for concurrency, distribution and fault tolerance.
Erlang Quickstart

[H2] What is OTP?
OTP is set of Erlang libraries and design principles providing middle-ware to
develop these systems. It includes its own distributed database, applications to interface
towards other languages, debugging and release handling tools.
Getting Started with OTP

[H2] News

[H3] Native Records on the Podcast BEAM There, Done That
May 28, 2026 by Björn Gustavsson

Native Records on the Podcast BEAM There, Done That

[H3] Erlang/OTP 29 Highlights
May 18, 2026 by Björn Gustavsson

Erlang/OTP 29 is finally here. This blog post introduces the new
features that we are most excited about.

[H3] Erlang/OTP 29.0
May 13, 2026 by Henrik Nord

Erlang/OTP 29.0

[H2] Participate

[IMG: Join the Erlang Ecosystem Foundation]
1141 chars
SUB-PAGE (https://erlang.org/downloads/) Downloads – Erlang/OTP
[H3] Compiling Erlang from source #
You can build Erlang from source on your own, following the building and installation instructions. In a nutshell to install a pre-built archive you need only do:
./configure && make && make install
If you clone the release from git, there may be some additional steps needed depending on which version of Erlang/OTP you are compiling. So always make sure to read the build and install instruction of the release you are compiling.
You can also use third-party tools such as Kerl, asdf or mise to compile Erlang. They help to remove the differences between Erlang/OTP releases and the OS you are compiling on.
[H3] Pre-built Binary Packages #
Most OS package managers provide pre-built binary packages.
For Homebrew on macOS: brew install erlang
For MacPorts on macOS: port install erlang
For Ubuntu and Debian: apt-get install erlang
For Fedora: dnf install erlang
For ArchLinux and Manjaro: pacman -S erlang
For FreeBSD: pkg install erlang
For Github Actions: setup-beam
For docker: docker run -it erlang
Note: Most OS package managers take some time to get the latest versions.
So if you want a specific version the recommendation is to build it yourself.
[H3] License
Since Erlang/OTP 18.0, Erlang/OTP is released under Apache License 2.0. The older releases prior to Erlang/OTP 18.0 were released under Erlang Public License (EPL), a derivative work of the Mozilla Public License (MPL).
1452 chars
SUB-PAGE (https://erlang.org/doc/getting_started/intro.html) Introduction — Erlang System Documentation v29.0.1
Search erlang documentation

Search erlang documentation
Search erlang documentation

Settings

[H1] Introduction

Copy Markdown

View Source
This section is a quick start tutorial to get you started with Erlang.
Everything in this section is true, but only part of the truth. For example,
only the simplest form of the syntax is shown, not all esoteric forms. Also,
parts that are greatly simplified are indicated with manual. This means that a
lot more information on the subject is to be found in the Erlang book or in
Erlang Reference Manual.
[H2] Prerequisites
The reader of this section is assumed to be familiar with the following:Computers in generalBasics on how computers are programmed
[H2] Omitted Topics
The following topics are not treated in this section:References.Local error handling (catch/throw).Single direction links (monitor).Handling of binary data (binaries / bit syntax).List comprehensions.How to communicate with the outside world and software written in other
languages (ports); this is described in
Interoperability Tutorial.Erlang libraries (for example, file handling).OTP and (in consequence) the Mnesia database.Hash tables for Erlang terms (ETS).Changing code in running systems.

← Previous Page

Patching OTP Applications

Next Page →

Sequential Programming
1319 chars
SUB-PAGE (https://erlang.org/doc/design_principles/des_princ.html) Overview — Erlang System Documentation v29.0.1
Search erlang documentation

Search erlang documentation
Search erlang documentation

Settings

[H1] Overview

Copy Markdown

View Source
The OTP Design Principles define how to structure Erlang code in terms of
processes, modules, and directories.
[H2] Supervision Trees
A basic concept in Erlang/OTP is the supervision tree. This is a process
structuring model based on the idea of workers and supervisors:Workers are processes that perform computations and other actual work.Supervisors are processes that monitor workers. A supervisor
can restart a worker if something goes wrong.The supervision tree is a hierarchical arrangement of code into supervisors
and workers, which makes it possible to design and program fault-tolerant
software.In the following figure, square boxes represent supervisors and circles
represent workers:---
title: Supervision Tree
---
flowchart
sup1[Type 1 Supervisor] --- sup2[Type 1 Supervisor] --- worker1((worker))
sup1 --- sup1a[Type A Supervisor]
sup1a --- sup2a[Type A Supervisor] --- worker2((worker))
sup1a --- sup3[Type 1 Supervisor]
sup3 --- worker3((worker))
sup3 --- worker4((worker))
[H2] Behaviours
In a supervision tree, many of the processes have similar structures
and follow similar patterns. For example, the supervisors share a
similar structure, with the sole distinction lying in the child
processes they supervise. Many of the workers are servers in a
server-client relation, finite-state machines, or event handlers.Behaviours are formalizations of these common patterns. The idea is to divide
the code for a process in a generic part (a behaviour module) and a specific
part (a callback module).The behaviour module is part of Erlang/OTP. To implement a process such as a
supervisor, the user only needs to implement the callback module, which is to
export a pre-defined set of functions, the callback functions.The following example illustrates how code can be divided into a generic and a
specific part. Consider the following code (written in plain Erlang) for a
simple server, which keeps track of a number of "channels". Other processes can
allocate and free the channels by calling the functions alloc/0 and free/1,
respectively.-module(ch1).
-export([start/0]).
-export([alloc/0, free/1]).
-export([init/0]).
start() ->
spawn(ch1, init, []).
alloc() ->
ch1 ! {self(), alloc},
receive
{ch1, Res} ->
Res
end.
free(Ch) ->
ch1 ! {free, Ch},
ok.
init() ->
register(ch1, self()),
Chs = channels(),
loop(Chs).
loop(Chs) ->
receive
{From, alloc} ->
{Ch, Chs2} = alloc(Chs),
From ! {ch1, Ch},
loop(Chs2);
{free, Ch} ->
Chs2 = free(Ch, Chs),
loop(Chs2)
end.The code for the server can be rewritten into a generic part server.erl:-module(server).
-export([start/1]).
-export([call/2, cast/2]).
-export([init/1]).
start(Mod) ->
spawn(server, init, [Mod]).
call(Name, Req) ->
Name ! {call, self(), Req},
receive
{Name, Res} ->
Res
end.
cast(Name, Req) ->
Name ! {cast, Req},
ok.
init(Mod) ->
register(Mod, self()),
State = Mod:init(),
loop(Mod, State).
loop(Mod, State) ->
receive
{call, From, Req} ->
{Res, State2} = Mod:handle_call(Req, State),
From ! {Mod, Res},
loop(Mod, State2);
{cast, Req} ->
State2 = Mod:handle_cast(Req, State),
loop(Mod, State2)
end.And a callback module ch2.erl:-module(ch2).
-export([start/0]).
-export([alloc/0, free/1]).
-export([init/0, handle_call/2, handle_cast/2]).
start() ->
server:start(ch2).
alloc() ->
server:call(ch2, alloc).
free(Ch) ->
server:cast(ch2, {free, Ch}).
init() ->
channels().
handle_call(alloc, Chs) ->
alloc(Chs). % => {Ch,Chs2}
handle_cast({free, Ch}, Chs) ->
free(Ch, Chs). % => Chs2Notice the following:The code in server can be reused to build many different servers.The server name, in this example the atom ch2, is hidden from the users of
the client functions. This means that the name can be changed without
affecting them.The protocol (messages sent to and received from the server) is also hidden.
This is good programming practice and allows one to change the protocol
without changing the code using the interface functions.The functionality of server can be extended without having to change ch2
or any other callback module.In ch1.erl and ch2.erl above, the implementation of channels/0, alloc/1,
and free/2 has been intentionally left out, as it is not relevant to the
example. For completeness, one way to write these functions is given below. This
is an example only, a realistic implementation must be able to handle situations
like running out of channels to allocate, and so on.channels() ->
{_Allocated = [], _Free = lists:seq(1, 100)}.
alloc({Allocated, [H|T] = _Free}) ->
{H, {[H|Allocated], T}}.
free(Ch, {Alloc, Free} = Channels) ->
case lists:member(Ch, Alloc) of
true ->
{lists:delete(Ch, Alloc), [Ch|Free]};
false ->
Channels
end.Code written without using behaviours can be more efficient, but the increased
efficiency is at the expense of generality. The ability to manage all
applications in the system in a consistent manner is important.Using behaviours also makes it easier to read and understand code written by
other programmers. Improvised programming structures, while possibly more
efficient, are always more difficult to understand.The server module corresponds, greatly simplified, to the Erlang/OTP behaviour
gen_server.The standard Erlang/OTP behaviours are:gen_serverFor implementing the server of a client-server relationgen_statemFor implementing state machinesgen_eventFor implementing event handling functionalitysupervisorFor implementing a supervisor in a supervision treeThe compiler understands the module attribute -behaviour(Behaviour) and issues
warnings about missing callback functions, for example:-module(chs3).
-behaviour(gen_server).
...
3> c(chs3).
./chs3.erl:10: Warning: undefined call-back function handle_call/3
{ok,chs3}
[H2] Applications
Erlang/OTP comes with a number of components, each implementing some specific
functionality. Components are with Erlang/OTP terminology called applications.
Examples of Erlang/OTP applications are Mnesia, which has everything needed for
programming database services, and Debugger, which is used to debug Erlang
programs. The minimal system based on Erlang/OTP consists of the following two
applications:Kernel - Functionality necessary to run ErlangSTDLIB - Erlang standard librariesThe application concept applies both to program structure (processes) and
directory structure (modules).The simplest applications do not have any processes, but consist of a collection
of functional modules. Such an application is called a library application. An
example of a library application is STDLIB.An application with processes is easiest implemented as a supervision tree using
the standard behaviours.How to program applications is described in Applications.
[H2] Releases
A release is a complete system made from a subset of Erlang/OTP
applications and a set of user-specific applications.How to program releases is described in Releases.How to install a release in a target environment is described in
Creating and Upgrading a Target System in System Principles.
[H2] Release Handling
Release handling is upgrading and downgrading between different versions of a
release, in a (possibly) running system. How to do this is described in
Release Handling.

← Previous Page

Support, Compatibility, Deprecations, and Removal

Next Page →

gen_server Behaviour
7538 chars
🧭 Industry Context — common generic-claim patterns in Software, SaaS & Tech Products to weigh the text against
Generic Claims: the all-in-one platform, trusted by thousands of companies, increase productivity by X percent, save hours every week, the leading platform for, built for teams of all sizes…
Red Flags: AI claims without explaining what the AI does, customer logos without case study or testimonial evidence, no live product access or demo, SOC 2 claims without audit period or report availability, productivity claims without methodology, pricing hidden behind sales calls only…
Semantic Drift Patterns: homepage claims AI-powered but product is rules-based, claims enterprise-grade but pricing page shows startup tiers only, homepage shows Fortune 500 logos but case studies are small businesses, claims all-in-one but integration page shows critical missing pieces, free plan promoted but core features require expensive upgrade…
Proof Expectations: live product demo or free trial access, specific feature documentation with screenshots, verified customer logos with published case studies, third-party review scores on G2, Capterra, or TrustRadius, published uptime SLA and status page, security certifications with audit dates…