- Published on
Modern Erlang and BEAM in 2026 — OTP 27, OTP 28 Preview, Cowboy 3, Bandit, Khepri, Gleam, Nerves, AtomVM Deep Dive
- Authors

- Name
- Youngju Kim
- @fjvbn20031
Prologue — Why a 30-Year-Old VM Is Still Compelling in 2026
- A team at Ericsson building telecom switches creates a new language. Its name: Erlang. Its single purpose: systems that do not die. Telephone exchanges with nine 9s of availability — 99.9999999%.
Forty years later, in 2026, Erlang is no longer just a telecom language. WhatsApp runs two billion users' messages on BEAM. Discord routes voice and text for hundreds of millions of people through Elixir. Klarna processes payment transactions on Erlang. RabbitMQ sits on the backbone of essentially every microservice architecture, and Akamai's DNS runs on Erlang.
BEAM has not stood still. OTP 27 shipped in May 2024, and OTP 28 is moving from preview to GA. Cowboy 3 has reworked HTTP/2 and WebSocket. Bandit offers a pure-Elixir alternative to Cowboy. The RabbitMQ team put Khepri on top of Raft as a Mnesia successor. gleam brought static types to BEAM. Nerves has captured embedded Linux, and AtomVM has pushed even into ESP32 microcontrollers.
This article is a full map of the BEAM ecosystem in 2026. New features in OTP 27 and 28, the HTTP stack, distributed data, embedded, new languages, and who actually uses this in production.
"Erlang lets us get more done with fewer people." — Jan Koum, WhatsApp co-founder, back when 50 engineers were running 900 million users.
1. The 2026 Erlang/BEAM Map — Why It Still Compels
First, what BEAM is and why it is fundamentally different from other virtual machines.
Four Core Assets of BEAM
- Lightweight processes (green processes) — Not OS threads. Virtual processes inside BEAM. About 300 bytes each. You can spawn millions on a single node.
- Preemptive scheduler — Different from Go's cooperative scheduler. BEAM uses reduction counts to force context switches. One process spinning in an infinite loop will not starve the others.
- Share-nothing message passing — No shared memory between processes. All communication is via messages. No locks. Whole categories of deadlocks simply disappear.
- OTP (Open Telecom Platform) — Behaviors like supervisor, gen_server, gen_statem. A 30-year-validated standard library for distribution and fault tolerance.
Where BEAM Shines vs Where It Doesn't
Shines Doesn't shine
──────────────────────── ────────────────────
Massive concurrent connections (millions) CPU-bound number crunching
Real-time messaging / chat Single-threaded throughput
Distributed systems / clustering Machine learning training
Long-lived connections (LiveView) Desktop GUI apps
Fault-tolerance-critical systems Systems programming
Protocol gateways (MQTT, AMQP) Game engines
The principle: places where concurrency, not CPU, is the bottleneck. And places where death is not allowed.
One-Page View of the 2026 BEAM Ecosystem
┌────────────────────────────────────────┐
│ BEAM VM │
│ (JIT, ETS, supervisor, OTP) │
└───────┬────────────────┬───────────────┘
│ │
┌─────────────┼───┐ ┌───────┼──────────┐
│ │ │ │ │ │
Erlang Elixir gleam Lustre Phoenix
│ │ │ (web) (LiveView)
│ │ │
▼ ▼ ▼
┌────────┐ ┌─────────┐ ┌─────────┐
│Cowboy 3│ │ Bandit │ │ AtomVM │
│ HTTP │ │(for Plug│ │ (ESP32) │
└────────┘ └─────────┘ └─────────┘
Storage: Mnesia / Khepri (Raft) / ETS / DETS
Distribution: distributed Erlang / partisan
Embedded: Nerves (Linux) / AtomVM (MCU)
Foundation: Erlang Ecosystem Foundation (EEF)
The rest of this article walks each part of that map in order.
2. Erlang/OTP 27 (May 2024) — Rediscovering String Interpolation and persistent_term
Erlang/OTP 27 shipped in May 2024. As of May 2026 most production systems are either on 27 or migrating to it. The three most visible changes.
2-1. Triple-Quoted Strings and String Interpolation
Erlang lived for 30 years without string interpolation. It finally landed in 2026 — and in two forms.
%% Triple-quoted string (OTP 27)
Greeting = """
Hello, World!
Multi-line, no escaping needed.
""",
%% Sigil form (~b for binary)
Name = <<"Alice">>,
Greeting2 = ~b"Hello, #{Name}!".
%% => <<"Hello, Alice!">>
The ~b sigil produces a binary string with interpolation, and ~B produces a non-interpolated binary. The design is similar to Elixir's ~s and ~S sigils.
Reality: Erlang users have written
io_lib:format("Hello, ~p!", [Name])for thirty years. Now it can be~b"Hello, #{Name}!". Code reads much better.
2-2. set_node_lookup_node / Node Discovery Improvements
Node discovery in distributed Erlang traditionally relied on EPMD (Erlang Port Mapper Daemon). OTP 27 formalized a callback API that lets you bypass EPMD and register node names directly.
- This was painful in container environments (Kubernetes), where EPMD became awkward.
- Libraries like
libclusteralready did similar work; OTP 27 turns that pattern into a standard interface.
2-3. persistent_term Improvements — Faster Reads
persistent_term is the cousin of ETS used for almost-never-changing global constants. Writes are very expensive (they trigger a system-wide GC), but reads are essentially zero cost.
OTP 27 cleaned up the internals to reduce memory footprint and write-time GC cost. Even better for almost-permanent data like config, keys, or routing tables.
%% Write once, read billions of times
persistent_term:put({config, max_connections}, 100000),
%% Almost free on the hot path
Max = persistent_term:get({config, max_connections}).
2-4. JIT Improvements and Compiler Diagnostics
- BEAMAsm JIT stabilized on ARM64 (direct wins on Apple Silicon and AWS Graviton).
- Compiler warnings are more accurate and the error messages friendlier.
- The maps module gained
iterator/2,filtermap/2, and friends.
OTP 27 Migration Checklist
□ Update Rebar3 / Mix to OTP 27 compatible versions
□ Re-run Dialyzer (subtle type-system changes)
□ If using EPMD replacement callbacks, check net_kernel config
□ Triple-quoted strings need IDE support (Erlang LS, ElixirLS)
□ Verify any third-party deps that pin to older OTP (most are fine)
3. OTP 28 Preview — What's Coming Next
As of May 2026, OTP 28 is in release candidate. GA is targeted for summer 2026. The headline changes.
3-1. Additional JIT Optimizations
- BEAMAsm reworked register allocation, giving 10 to 15 percent extra performance on hot loops.
- Better function inlining heuristics.
3-2. Standard Library Extensions for set and map
%% Expected new helpers in OTP 28
maps:groups_from_list(fun(X) -> X rem 2 end, [1,2,3,4,5]).
%% => #{0 => [4,2], 1 => [5,3,1]}
%% Analogous helpers on the set module
3-3. Modernized SSL Stack — TLS 1.3 Completion
- Full support for TLS 1.3 0-RTT.
- Experimental support for post-quantum key exchange (Kyber / ML-KEM).
3-4. Tighter logger and telemetry Integration
- More infrastructure for OpenTelemetry compatibility.
- Standardized structured logging metadata.
3-5. Distributed Monitoring Improvements
- Better error messages for
monitor/2andlink/1across nodes. - Clearer recovery behavior when monitor messages are lost across a netsplit.
Summary: OTP 28 is not a revolution. It is polish. It is a great example of how a 30-year-old system keeps getting better, year after year.
4. Cowboy 3 — BEAM's Default HTTP Server
Cowboy is the small, fast Erlang HTTP server created by Loïc Hoguin. It underpins Plug, Phoenix, the RabbitMQ Management UI, and basically every Erlang or Elixir web stack as a default.
Cowboy 3 landed in late 2024. The headline changes.
4-1. Full HTTP/2 Compliance
- Cowboy 2 supported HTTP/2 but had some corner-case deviations from RFC 9113.
- Cowboy 3 swept through the spec again, with fuzzing tests added.
- In particular, GOAWAY handling and flow-control window race conditions were fixed.
4-2. WebSocket Stabilization
- Cleaned up permessage-deflate compression options.
- Patched a memory-leak edge case in fragmented (framed) message handling.
4-3. HTTP/3 — Experimental
- HTTP/3 over QUIC is now in experimental status.
- Not yet production-recommended, but some teams have begun beta evaluations.
4-4. Simple Cowboy Handler Example
%% After adding cowboy to rebar.config
-module(hello_handler).
-export([init/2]).
init(Req0, State) ->
Req = cowboy_req:reply(200,
#{<<"content-type">> => <<"text/plain">>},
<<"Hello from Cowboy 3!">>,
Req0),
{ok, Req, State}.
%% Register on the router
start() ->
Dispatch = cowboy_router:compile([
{'_', [{"/", hello_handler, []}]}
]),
{ok, _} = cowboy:start_clear(my_http_listener,
[{port, 8080}],
#{env => #{dispatch => Dispatch}}).
Notable Systems Using Cowboy
- Phoenix (Elixir web framework) — one of the default adapters.
- RabbitMQ Management Plugin.
- Parts of Akamai's edge services.
- Internal tools at WhatsApp.
5. Bandit — A Pure-Elixir HTTP Server
Cowboy is written in Erlang. Plug/Phoenix is written in Elixir. The bridge has historically been an adapter (Plug.Cowboy), but some users wanted "what if the entire Elixir stack were Elixir?"
Bandit (started in 2022, led by Mat Trudel) is that answer.
5-1. What Bandit Aims For
Cowboy: Erlang -> Elixir adapter (Plug.Cowboy) -> Plug/Phoenix
Bandit: Elixir -> -> Plug/Phoenix
- Pure Elixir implementation of HTTP/1.1, HTTP/2, and WebSocket.
- Direct integration with Plug (no adapter layer).
- 10 to 30 percent faster than Cowboy on some microbenchmarks.
5-2. Integration with Phoenix
Since Phoenix 1.7, Bandit can be used as a drop-in replacement for Plug.Cowboy.
# config/config.exs
config :my_app, MyAppWeb.Endpoint,
adapter: Bandit.PhoenixAdapter,
http: [port: 4000]
One line. Phoenix LiveView, channels, controllers all keep working.
5-3. Bandit vs Cowboy — 2026 Comparison
Cowboy 3 Bandit
Host language Erlang Elixir
HTTP/1.1 Production Production
HTTP/2 RFC 9113 RFC 9113
HTTP/3 Experimental Not yet
WebSocket Yes Yes
Plug integration Adapter Native
Ops track record 10+ years 3 to 4 years
Recommended for Conservative shops New Phoenix projects
5-4. Which One to Choose
- Existing Erlang systems → Cowboy 3.
- New Phoenix projects → Bandit is becoming the default.
- You need HTTP/3 → Cowboy 3 (today).
- You want an all-Elixir codebase → Bandit.
6. Khepri — The RabbitMQ Team's Mnesia Successor
Mnesia is the distributed DBMS that Erlang has shipped with since the 1990s. Hybrid memory and disk, transactions, ETS-compatible interface. But its netsplit behavior is a well-known weak spot — when a split happens, both sides keep running, the data diverges, and manual intervention is needed to rejoin.
The RabbitMQ team (under Pivotal, then VMware, now Broadcom) built Khepri to attack that problem head-on.
6-1. The Core Idea of Khepri
"Replace Mnesia, but put Raft consensus under it."
- A tree-shaped key-value store (think Zookeeper or etcd data model).
- Every write goes through Raft → a majority must be alive to commit a write.
- Splits no longer end with both sides claiming truth (the minority side cannot write).
- Written in Erlang/OTP. No external dependencies.
6-2. The Khepri Data Model
%% Path-based tree structure
ok = khepri:put([app, config, max_users], 1000),
{ok, 1000} = khepri:get([app, config, max_users]),
%% Wildcard queries
{ok, Map} = khepri:get_many([app, config, ?KHEPRI_WILDCARD_STAR]).
The design is very close to Zookeeper's znodes and etcd's key tree.
6-3. Adoption in RabbitMQ
- Since RabbitMQ 4.0 (September 2024) Khepri can be selected as the metadata store.
- It is on track to become the default in later 4.x releases.
- It replaces the internal Mnesia used by RabbitMQ for metadata (queue definitions, users, vhosts).
- Message bodies are handled by separate queue engines (quorum queues, etc.), so Khepri focuses on the control plane.
6-4. Using Khepri in Your Own System
%% Add khepri to rebar.config
{deps, [
{khepri, "0.14.0"}
]}.
%% Start it
{ok, _} = khepri:start(),
%% Transaction
khepri:transaction(fun() ->
khepri_tx:put([users, alice], #{role => admin}),
khepri_tx:put([users, bob], #{role => user})
end).
Bottom line: Khepri is quietly replacing Mnesia. For new distributed BEAM systems that need a metadata store, Khepri is increasingly the sensible default.
7. Mnesia and partisan — Distributed Data and Distributed Communication
7-1. Mnesia — Still Alive
The arrival of Khepri does not erase Mnesia. In 2026:
- It is still used where transactions over table-shaped data are needed, and where the ETS-style API is desired.
- ejabberd (XMPP server), some game servers, telecom equipment still ship Mnesia inside.
- The weaknesses have not changed: weak netsplit story, operational overhead on large datasets.
Rules of thumb:
- Small data, small number of nodes → Mnesia is still fine.
- Netsplit consistency matters → Khepri or an external DB.
- Pure cache → ETS alone is enough.
7-2. partisan — A Rethink of Distributed Erlang Itself
The default distributed Erlang (net_kernel) assumes a full-mesh topology. Every node is directly connected to every other node. Past about 100 nodes you start to see message storms and head-of-line blocking.
partisan (Christopher Meiklejohn and others) redesigned this.
distributed Erlang: N nodes -> N*(N-1)/2 connections (full mesh)
partisan: Multiple topology options
- full mesh
- hyparview (peer-to-peer overlay)
- client-server
- PG2-based static groups
The key ideas:
- Multi-channel — multiple TCP connections between a pair of nodes. Small messages no longer get blocked behind large ones.
- Monolithic or P2P — pick a topology.
- Backwards-compatible — keep the
gen_serverinterface; swap the transport underneath.
As of 2026, partisan is:
- Born out of academic research and now adopted in some production systems (IoT backends, game servers especially).
- Not mainstream — distributed Erlang is still the default for most teams — but more teams reach for partisan on large clusters.
8. Nerves — Embedded Erlang/Elixir
Nerves, led by Frank Hunleth, is an embedded framework with a single big idea:
"Run BEAM on Linux. The entire userland is Elixir/Erlang."
8-1. What Nerves Aims For
- Raspberry Pi, BeagleBone, industrial single-board computers.
- Reduce the complexity of traditional embedded Linux distros (buildroot, yocto) and produce reproducible firmware builds.
- Safe OTA updates through A/B partitions.
- Apply BEAM's supervisor model to the entire firmware.
8-2. A Typical Nerves Project
# Create a new Nerves project targeting Raspberry Pi 4
mix nerves.new my_iot_device --target rpi4
cd my_iot_device
# Build the firmware
MIX_TARGET=rpi4 mix deps.get
MIX_TARGET=rpi4 mix firmware
# Burn to SD card
MIX_TARGET=rpi4 mix firmware.burn
The firmware image bundles the bootloader, the Linux kernel, BEAM, and your Elixir application. There is almost nothing else in userland.
8-3. Real-World Use Cases
- FarmBot — open-source agricultural robot.
- GRiSP — industrial embedded boards running Erlang nearly bare-metal.
- Logistics and warehouse automation — some companies ship Nerves-based PLC replacements.
- Audio gear, digital signage.
8-4. NervesHub — OTA Fleet Management
NervesHub, also built by the Nerves team, is a centralized firmware update system. You can do staged rollouts across a fleet of devices.
Point: Nerves is the empirical demonstration that "embedded works fine when it runs inside a BEAM supervisor."
9. gleam — A Statically-Typed BEAM Language
gleam, created by Louis Pilfold and started in 2016, is a statically-typed functional language that targets BEAM. It hit 1.0 and took seed funding in 2024, and started attracting real attention.
9-1. What gleam Offers
import gleam/io
import gleam/list
pub fn main() {
let numbers = [1, 2, 3, 4, 5]
let doubled = list.map(numbers, fn(n) { n * 2 })
io.debug(doubled)
}
- Type inference — you barely need to annotate variables; all types are resolved at compile time.
- Expression-based — functional style very much in the Erlang/Elixir family.
- Two targets — compiles to BEAM and to JavaScript. (Yes, gleam can produce JS.)
- Erlang FFI — call existing Erlang/OTP libraries directly.
9-2. Why Bring Static Types to BEAM?
- Elixir and Erlang are dynamically typed. Dialyzer (success typing) helps, but has limits.
- gleam was designed from day one around strong static types (Hindley-Milner family).
- Result: if it compiles, most mistakes are caught — similar in spirit to Rust or Haskell.
9-3. A Simple OTP-Style Actor (gleam_otp)
import gleam/erlang/process
import gleam/otp/actor
pub fn main() {
let assert Ok(subject) = actor.start(0, handle_message)
process.send(subject, Increment)
process.send(subject, Increment)
// incremented twice
}
pub type Message {
Increment
GetCount(reply_to: process.Subject(Int))
}
fn handle_message(message: Message, count: Int) -> actor.Next(Message, Int) {
case message {
Increment -> actor.continue(count + 1)
GetCount(reply_to) -> {
process.send(reply_to, count)
actor.continue(count)
}
}
}
OTP, but typed. The shape of the messages a process can receive is checked at compile time.
9-4. What Has Happened Since gleam 1.0
- The ecosystem is growing fast — package count on hex.pm has accelerated.
- 2024 seed round — Pilfold can work on gleam full-time.
- JavaScript target — you can ship some gleam code to the frontend.
- Community vibe — the Elixir community has generally received gleam warmly.
9-5. When to Pick gleam
- When you want the safety of static types on BEAM.
- When you want BEAM's concurrency and fault tolerance, plus type safety.
- When you can start a new project (migrating an existing Elixir codebase is a different conversation).
10. Lustre — gleam's Web Framework
Lustre, by Hayleigh Thompson, is gleam's frontend framework. It is heavily inspired by Elm and uses The Elm Architecture (TEA) pattern.
10-1. The Lustre Model
┌─────────┐ Msg ┌─────────┐
│ View │ ───────────>│ Update │
│ (HTML) │ │ (model │
└─────────┘ <────────│ │ changes)│
▲ Model └─────────┘
│
└──── user interaction ────┐
│
▼
(browser)
10-2. A Simple Counter (Lustre)
import lustre
import lustre/element/html.{button, div, text}
import lustre/event
pub fn main() {
let app = lustre.simple(init, update, view)
let assert Ok(_) = lustre.start(app, "#app", Nil)
}
fn init(_) {
0
}
pub type Msg {
Incr
Decr
}
fn update(model: Int, msg: Msg) -> Int {
case msg {
Incr -> model + 1
Decr -> model - 1
}
}
fn view(model: Int) {
div([], [
button([event.on_click(Decr)], [text("-")]),
text(int.to_string(model)),
button([event.on_click(Incr)], [text("+")]),
])
}
10-3. Lustre's Two Modes
- Client-side — compile gleam to JavaScript and run in the browser.
- Server components — Phoenix LiveView style; server holds the state, the browser is a thin client.
The server-components mode is similar to LiveView but adds gleam's type safety as a differentiator.
10-4. Where Lustre Sits in 2026
- Lustre is not yet mainstream.
- Small projects, side projects, and teams that want a gleam full stack are adopting it.
- It is in the phase of exploring its potential as a LiveView alternative.
11. AtomVM — Erlang on ESP32
AtomVM, by Davide Bettio and others, is a VM that runs BEAM bytecode on microcontrollers.
11-1. What AtomVM Targets
- ESP32 (Wi-Fi/Bluetooth-equipped MCU, very cheap)
- STM32
- Raspberry Pi Pico (RP2040)
These boards are too small to run Linux (typically hundreds of kilobytes to a few megabytes of RAM). Nerves cannot go here, but AtomVM can.
11-2. How It Works
- Reads standard BEAM bytecode (
.beamfiles) and interprets/runs them on the microcontroller. - Supports only a subset of the standard library (memory constraints).
- OTP patterns like supervisor and gen_server work.
11-3. "Hello, Erlang" on ESP32
-module(blink).
-export([start/0]).
start() ->
Pin = 2,
gpio:set_pin_mode(Pin, output),
loop(Pin, high).
loop(Pin, State) ->
gpio:digital_write(Pin, State),
timer:sleep(500),
NextState = case State of
high -> low;
low -> high
end,
loop(Pin, NextState).
# Compile and flash to ESP32 (rough outline)
erlc blink.erl
atomvm_packbeam blink.avm blink.beam
esptool.py write_flash 0x250000 blink.avm
You start with the LED-blink classic and grow into BLE-based IoT devices, small message gateways, and so on.
11-4. AtomVM vs Nerves
AtomVM Nerves
Target MCU (ESP32, STM32) SBC (Pi, BeagleBone)
RAM Hundreds of KB Multiple GB possible
OS None (bare metal / FreeRTOS) Linux
BEAM AtomVM (subset) Full OTP
Use case Sensor nodes, BLE devices Edge gateways
The smallest node uses AtomVM, the hub that aggregates them uses Nerves, and the cloud backend uses full OTP. The whole hierarchy on the same family of language.
11-5. Where AtomVM Stands Today
- AtomVM 0.6 series is in stabilization.
- Supports both Erlang and Elixir (both compile to
.beam). - An active but small community. The natural home for BEAM users interested in IoT and edge.
12. RabbitMQ — The Poster Child of Erlang
RabbitMQ has been covered in its own deep dive elsewhere, so we will be brief. The key point is that this single project did more than any other to bring Erlang into mainstream infrastructure.
12-1. Why RabbitMQ Picked Erlang
- An AMQP message broker has to handle tens to hundreds of thousands of concurrent connections by nature.
- It cannot die — supervisor trees match perfectly.
- Distributed clustering was needed from day one.
- Erlang was literally designed for exactly this kind of workload.
12-2. RabbitMQ in 2026
- Version 4.x.
- Quorum Queues are the default. Raft-based queues replacing the older classic mirrored queues.
- Khepri is moving in as the metadata store.
- Supports MQTT 5.0 and Streams (Kafka-style).
12-3. The Effect on the Erlang Ecosystem
- The biggest single force in moving Erlang from "telco language" to mainstream infrastructure component.
- Many companies first experienced "huh, this Erlang system really doesn't die" through RabbitMQ.
13. Real Usage — WhatsApp, Klarna, Discord, Riot, Cisco, Akamai
Short case studies of companies that take BEAM seriously.
13-1. WhatsApp — The Erlang Scale Legend
- Founded in 2009. Jan Koum came from ejabberd (Erlang XMPP), so Erlang was the choice from day one.
- The system that first publicly demonstrated 2 million concurrent connections on a single server.
- At the time of the 2014 Facebook acquisition, 50 engineers ran 900 million users.
- Even after the acquisition, the core remains Erlang on FreeBSD.
- "Fewer people, massive concurrency" became BEAM's marketing tagline.
13-2. Klarna — Erlang at Fintech Scale
- Swedish BNPL (buy now, pay later) fintech.
- Erlang since 2005. Payment transaction processing, parts of risk evaluation.
- Gradual migration from a monolithic Erlang system to microservices, with Erlang still at the core.
- Heavy use of Erlang's hot code swap for zero-downtime deploys.
13-3. Discord — Erlang/Elixir Hybrid
- Voice/text gateway is in Elixir (BEAM).
- Handles "millions of users in one channel receiving messages" through BEAM's process model.
- Some core data plane code is rewritten in Rust (honest about what BEAM is not great at).
- But sessions, routing, real-time communication remain in Elixir.
13-4. Riot Games — Erlang for Chat
- League of Legends in-game chat runs on an ejabberd-derived Erlang system.
- Handles tens of millions of concurrent chat users reliably.
13-5. Cisco — XMPP / Telecom Infra
- Erlang in some telecom equipment, IP phones, and collaboration tools backends.
- Parts of Cisco Webex are reportedly built on Erlang.
13-6. Akamai — DNS in Parts
- The CDN giant runs some DNS infrastructure on Erlang-based services.
- Hundreds of thousands of queries per second benefit from BEAM's concurrency.
Common Threads
- Systems that cannot die.
- Tens of thousands to millions of concurrent connections.
- Messaging and real-time protocols.
- Distributed clustering.
Companies whose essential bottleneck is concurrency, not CPU.
14. Korea and Japan — BEAM in East Asia
BEAM is well-known in the West, but how does adoption look in East Asia?
14-1. Korea — Kakao, Telcos, Some Startups
- Kakao has used Erlang/Elixir at various times for messaging and notification fan-out infrastructure where BEAM fits naturally.
- Carrot (Danggn) — Phoenix has appeared in chat/push paths (mentioned in internal tech talks).
- Telcos — KT and SK Telecom have used Erlang-based middleware in parts of their telecom infrastructure. ejabberd-based messaging has also been used.
- Startups and game studios — some mobile game backends (matchmaking, chat servers) ship Elixir.
Reality: BEAM is not mainstream in Korea, but in companies whose essence is messaging or real-time, it is quietly used.
14-2. Japan — Pixiv, NTT, Telecom
- Pixiv has used Elixir/Erlang in parts of its messaging and notification systems at various times. Public conference talks exist.
- NTT uses Erlang-based middleware in some telecom backbones. Equipment vendors NEC and Fujitsu have similar patches.
- DMM has experimented with Elixir for some microservices.
- Drecom and others — some real-time game backends.
14-3. Why Adoption Looks Slower in East Asia
- The hiring pool is small — narrower market than Java, Go, or Rust.
- Functional language exposure in formal education is limited.
- Conservative corporate culture in Korea and Japan — preference for "proven" stacks. (Paradoxically BEAM is extremely proven, but local perception lags.)
- That said, in messaging, real-time, and IoT shops, adoption keeps trickling up.
15. Who Should Pick BEAM — Decision Guide
Finally, a pragmatic guide for "is BEAM right for this project in 2026?"
15-1. Where BEAM Wins
- Real-time messaging and chat — Discord, WhatsApp, parts of Slack backends.
- Message brokers — RabbitMQ proved it.
- Long-lived connections — large fan-out of WebSocket, MQTT, SSE.
- Distributed systems — clustering is built in from day one.
- Fault-tolerance-critical systems — supervisor trees, "let it crash" philosophy.
- Protocol gateways — XMPP, AMQP, MQTT, telecom signaling.
- IoT backends — tens of thousands of devices in concurrent connections.
15-2. Where BEAM Doesn't Win
- Heavy numerical work / ML training — CPU-bound workloads usually go through NIFs.
- Single-threaded throughput — Go, Rust, C++ are faster.
- Systems programming — kernels, drivers, game engines.
- Desktop GUI applications.
- Fast time-to-market with team hiring — talent is harder to find.
15-3. Language Choice — Erlang vs Elixir vs gleam
Erlang Elixir gleam
Types Dynamic Dynamic + dialyzer Static
Syntax Prolog-flavored Ruby-flavored Rust / Elm-flavored
Ecosystem Old, stable Most active Growing fast
Tooling rebar3 mix (excellent) gleam (clean)
Sweet spot Existing OTP systems New web / Phoenix Type-safe greenfield
Learning Steep due to syntax Smooth Fast for FP folks
Recommendations:
- New BEAM project, most cases → Elixir.
- You care a lot about type safety → gleam.
- You maintain an existing Erlang system → Erlang.
- You can mix them — they interoperate on the same BEAM.
15-4. HTTP Server Choice
- New Phoenix → Bandit.
- Existing Erlang/Cowboy stack → keep Cowboy 3.
- Need HTTP/3 → Cowboy 3.
15-5. Distributed Data Choice
- Small metadata, strong consistency → Khepri.
- Lots of transactional table data, small cluster → Mnesia.
- Cache or read-heavy → ETS (single node) or external KV (Redis, FoundationDB).
- Full OLTP/OLAP → external DB (PostgreSQL, ClickHouse, etc.).
15-6. Embedded Choice
- SBC (Pi, BeagleBone) → Nerves.
- MCU (ESP32, STM32) → AtomVM.
16. Closing — BEAM Is Not Going Anywhere
Over 40 years, BEAM went from the secret weapon of a telecom company to the backbone of the internet's messaging infrastructure. In 2026, BEAM:
- Is still being polished with OTP 27 and 28.
- Has a modernized HTTP stack with Cowboy 3 and Bandit.
- Is fixing distributed data's weak spots with Khepri.
- Has gained a type-safe option in gleam.
- Has expanded into embedded with Nerves and AtomVM.
BEAM's promise has not changed — "systems that do not die." What was needed in a 1980s telephone exchange is still needed in a 2026 LLM inference gateway, a message queue, an IoT backend, or a real-time collaboration tool.
If your system is the kind that has to keep many connections alive at once and absolutely cannot die, BEAM deserves a serious look. Messaging, payments, IoT, chat — whatever the domain.
BEAM will probably still be quietly running somewhere in 30 years. Maybe in 50. Telephone exchanges may be gone, but the kind of problem BEAM was built for never quite goes away.
References
- Erlang/OTP 27 release notes — https://www.erlang.org/news/170
- Erlang/OTP official docs — https://www.erlang.org/docs
- Erlang Ecosystem Foundation — https://erlef.org
- Cowboy official site — https://ninenines.eu
- Bandit on GitHub — https://github.com/mtrudel/bandit
- Khepri project — https://github.com/rabbitmq/khepri
- Khepri intro post (RabbitMQ team) — https://blog.rabbitmq.com/posts/2022/05/khepri-0-1-0-release/
- Mnesia user guide — https://www.erlang.org/doc/apps/mnesia/users_guide.html
- partisan — https://github.com/lasp-lang/partisan
- Nerves project — https://nerves-project.org
- NervesHub — https://www.nerves-hub.org
- Gleam official — https://gleam.run
- Gleam 1.0 announcement — https://gleam.run/news/gleam-version-1/
- Lustre — https://hexdocs.pm/lustre
- AtomVM — https://www.atomvm.net
- RabbitMQ — https://www.rabbitmq.com
- Phoenix Framework — https://www.phoenixframework.org
- Phoenix LiveView — https://hexdocs.pm/phoenix_live_view
- WhatsApp engineering (historical) — https://www.erlang-factory.com/conference/SFBay2012/speakers/RickReed
- Discord blog — https://discord.com/blog
- "Designing for Scalability with Erlang/OTP" (book) — Cesarini & Vinoski, O'Reilly
- "Programming Phoenix LiveView" (book) — Tate & Dwyer, Pragmatic Bookshelf