ErlangRT is a BEAM emulator in Rust, roughly half built
Erlang Replacement Therapy. Another attempt to make Erlang runtime (BEAM emulator) in Rust. Good news: I know what to do. Bad news: I have no clue how to Rust
At a glance
- What is it?
- Erlang Replacement Therapy is an attempt to write the Erlang runtime, the BEAM emulator, in Rust, and the repository tracks its own progress honestly: the term library at 80 percent, the external term format decoder at 70, 74 of 168 opcodes implemented and the VM loop at 45 percent. It suits someone studying how a BEAM works or experimenting with Rust, and it is an experiment rather than a usable Erlang.
- Who is it for?
- Adopt ErlangRT when you want to study how the BEAM emulator works, or want to experiment with a Rust implementation of a runtime, and you are prepared to read Erlang and Rust source side by side. Do not adopt it to run Erlang in production, because the project describes itself as an attempt, tracks a proof of concept, and the VM loop and opcodes are less than half done.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 129 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The progress list is the honest part
The README opens with a section titled Progress to the Proof of Concept, and it is the most valuable thing in the repository. The term library is at 80 percent, with a parenthetical noting that the remaining 80 percent are in progress. The external term format decoder is at 70 percent and the encoder at 0. The BEAM loader is mostly done. The VM and processes are at 40 percent. The VM loop and opcodes are at 45 percent, which the README quantifies as 74 of 168. Some basic BIFs are under 15 percent, and binaries, sub-binaries, the binary heap and the binary opcodes are under 20 percent. The repository description is candid in the same vein, calling it another attempt to make the Erlang runtime in Rust, and saying in the same breath that the author knows what to do and has no clue how to Rust. A project that publishes its own percentage completion is telling you something useful about how to treat it, and this one is more honest than most.
Where the project got to, and where it stops
The state of the implementation is not uniform, and the shape of it tells you where the difficulty lies. The term library being furthest along makes sense, because the external term format is a well defined serialisation and it is the boundary between Erlang and everything else. The encoder being at 0 while the decoder is at 70 is a sign that the project is built around consuming rather than producing term data, which is what an emulator loading precompiled BEAM files needs. The BEAM loader is mostly done, which is the piece that turns .beam files into loaded code, and the loader being nearly complete while the opcodes are less than half done means the emulator can load Erlang code it cannot yet execute much of. Binaries and the binary heap at under 20 percent is the largest single gap in the list, and binaries are where BEAM's performance characteristics actually live, since they are how large binary data avoids being copied on every operation.
The proof of concept is boot, and it does not boot
There is a screenshot captioned as trying to run init:boot/1, and the text around it says the tests in priv/test2.erl work while running make test tries to run init:boot/1 and produces the output shown. That is the precise state of the project in one sentence. init:boot/1 is the function that starts the Erlang node, loads the standard library, brings up the code server and the logger and everything else, and it is the conventional first milestone for a BEAM implementation because nothing else can run until it returns. Failing to complete it while passing the smaller tests in priv/test2.erl is the expected shape of a proof of concept: the pieces work in isolation, the boot sequence is the first thing to exercise all of them at once. The Makefile confirms the structure, with the test target running RUST_BACKTRACE=1 cargo +nightly run --bin ct_run, and a separate ct target that runs the same binary with numbered arguments under a tmp directory.
Building it means building Erlang first
The compiling section sets out the dependency that surprises people. The source assumes Erlang OTP 22 or newer source is present in a Git submodule in otp/, and that the stdlib and preload BEAM files are compiled and ready, and the Makefile takes care of it. The otp target does the work, running git submodule init, git submodule update, then entering the otp directory and running MAKE_FLAGS=-j8 ./otp_build setup. So the build order is Erlang first, then Rust. You need the latest Rust and Cargo via Rustup, and then the Makefile targets are the interface. make run runs the executable with whatever test arguments the developer has set, and the README is honest that you should not expect it to show any magical tricks. make doc builds the doc pages into target/doc/erlang_rt/. make test runs the tests. make build and make build-rel build without running, for the debug and release targets respectively. The build itself is cargo +nightly build, so a nightly Rust toolchain is a hard requirement rather than a preference.
The make targets available in the repository are:
cargo +nightly build
cargo +nightly run --bin erlexec
RUST_BACKTRACE=1 cargo +nightly run --bin ct_runThree crates, a code generator and a debugger target
The Cargo manifest is a workspace with three members, lib-erlangrt, erlexec and ct_run, and the layout matches the names. lib-erlangrt is the library that does the work, and it has its own Makefile with a codegen target, which the top-level Makefile calls before building, so the generated parts of the implementation are produced from something rather than checked in by hand. erlexec is the executable, the thing the run target launches, and ct_run is the test runner binary that the test and ct targets invoke. There is also a test-gede target for a graphical user interface for GDB, called gede, which passes the same arguments to the ct_run binary, so the emulator can be driven under a debugger with a visual interface rather than only through a terminal. The erlexec directory also holds the entry point for running BEAM code, and priv/ holds the test fixtures and the test build, since the build_tests target descends into priv and runs make there. The presence of .clang-format and rustfmt.toml alongside rustfmt-license.txt tells you the project keeps some formatting conventions for the C sources it pulls in, alongside Rust formatting for its own.
Where the author points for reference
The reference section names two things, and both are about understanding the BEAM rather than about Rust. The first is the BEAM Wisdoms site, which the author says they run, and the second is The BEAM book, for which the author says they are one of the editors. That second detail is worth a moment, because it means the reference is not a neutral pointer to an existing book but something the author helps write, which tells you the level of detail the project intends to work at. The editing and code navigation section says the author uses and strongly recommends IntelliJ IDEA CE with the IntelliJ-Rust plugin, available from the repositories tab inside IntelliJ, which is an unusual recommendation for a Rust project where most people would use rust-analyzer in a text editor, and it suggests a preference for a single IDE over an editor plus a language server. The project has a .gitmodules file, a CONTRIBUTING.rst, a CHANGELOG-style history in the repository and an MIT licence file, and the last push was on 2026-06-16 with no GitHub releases tagged.
Editorial conclusion
Adopt ErlangRT when you want to study how the BEAM emulator works, or want to experiment with a Rust implementation of a runtime, and you are prepared to read Erlang and Rust source side by side. Do not adopt it to run Erlang in production, because the project describes itself as an attempt, tracks a proof of concept, and the VM loop and opcodes are less than half done. Verify first that you can build Erlang OTP 22 or newer from the submodule and compile the stdlib and preload BEAM files, since the emulator expects them present, and that you have the nightly Rust toolchain the Makefile requires.
Frequently asked questions
How far along is the ErlangRT BEAM emulator?
The README tracks it: the term library is at 80 percent, the external term format decoder at 70 percent and the encoder at 0, the BEAM loader is mostly done, the VM and processes are at 40 percent, and the VM loop and opcodes at 45 percent, which is 74 of 168. Basic BIFs are under 15 percent and binaries, sub-binaries, the binary heap and the binary opcodes are under 20 percent.
What do the ErlangRT tests actually achieve?
The tests in priv/test2.erl work, while make test tries to run init:boot/1 and produces the output shown in the README screenshot. The boot sequence, which starts the node and loads the standard library, is the first thing that exercises all the components together and it is the part that does not yet complete.
What do I need to build ErlangRT?
Erlang OTP 22 or newer source in the otp/ Git submodule, with the stdlib and preload BEAM files compiled, which the Makefile's otp target handles by running git submodule init, git submodule update and then ./otp_build setup. You also need the latest Rust and Cargo via Rustup, and a nightly toolchain, since the build runs cargo +nightly build.
What crates make up the ErlangRT workspace?
Three members: lib-erlangrt for the implementation itself, which has its own codegen target, erlexec as the executable that the run target launches, and ct_run as the test runner binary invoked by the test and ct targets. There is also a test-gede target that drives the same binary under gede, a graphical user interface for GDB.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kvakvs-erlangrt)Was this useful?