Gleam 1.19.0 Compiles to Erlang Abstract Format Instead of Erlang Source and Flattens JavaScript Pattern Matching; 1.19.1 Followed Two Days Later
Gleam 1.19.0, dated October 5, 2026, replaces textual Erlang output with Erlang abstract forms; v1.19.1, dated October 7, fixes the export prelude commands.
Overview
The Gleam project published v1.19.0 of its compiler on 5 October 2026. In the release post on the Gleam project blog, Louis Pilfold writes that previously Gleam generated Erlang source code and now generates Erlang abstract forms. The project changelog heads the release “1.19.0 - 2026-10-05” and lists its entries under the release candidates 1.19.0-rc1 (2026-09-22), rc2 (2026-09-26) and rc3 (2026-10-01). A patch release, v1.19.1, is dated 2026-10-07.
What Changed in the Erlang Back End
According to the Gleam blog, Giacomo Cavalieri rewrote the Erlang code generator over the last few months, and the first stage of that rewrite shipped in v1.18.0. The post describes Erlang abstract forms as an intermediate representation used by the Erlang compiler, which lets Gleam skip the front half of that compiler. The changelog says compile times have been reduced for a typical Gleam package.
The blog post also says the runtime location metadata now points at the original Gleam source, so line numbers in BEAM crash reports and stacktraces are, in its words, perfectly accurate, where previously they could be inaccurate and point only to the nearest function. The post adds that the metadata could enable fuller Gleam support in debuggers such as edb, but says the project has not done any work on that itself.
The blog also compares build times using a benchmark based on José Valim’s langcompilebench project: compiling 100 modules, each containing 100 functions that return a “hello world” string. It compares v1.17.0 with v1.19.0 and also charts other languages. The post itself cautions that benchmarks are contrived and insufficient to draw hard conclusions, and the chart values are not stated in the post text, so this article does not repeat them.
The post explains why Gleam does not target BEAM bytecode directly: unlike Erlang source and abstract forms, it says, bytecode is not fixed, and keeping up with each virtual machine release would be a significant commitment. It notes that Elixir also compiles to Erlang via abstract forms.
JavaScript and TypeScript Output
Per the Gleam blog, John Downey changed pattern-matching output on the JavaScript target so that nested if statements are collapsed into a single condition with fewer intermediate variables. The post says this makes little-to-no change to bundle size once minified and compressed, but leaves fewer branches for JavaScript engines to optimise.
The same post says short list literals now compile to nested prepend(...) calls ending in empty rather than an arrayToList([1, 2, 3]) call. It credits Cavalieri, says the change is especially impactful for projects with many short lists such as those using the Lustre library, and says no improvement was recorded for longer lists, which keep the array-to-list approach.
For TypeScript declarations, the changelog lists overloads that narrow the variants of a custom type, giving Box$isFull<I>(value: Box$<I>): value is Full<I> as an example. The blog says the point is to stop the type parameter being generalised to unknown.
Build Tool, Language Server and Warnings
The blog says several changes by Rodrigo Álvarez are aimed at getting Gleam support into Elixir’s Mix and Erlang’s rebar3: compile-package gains a --no-dev flag, the compiler now generates the .app resource files when compiling to BEAM, and export package-information and export package-interface can print to stdout. The changelog notes that --no-dev is a rename of --src-only, and that compile-package gains an --otp-app-names flag. According to the blog, the language server now supports go-to-definition, find-references and renaming for labels, credited to Alistair Smith, and the WebAssembly build of the compiler gains a format_source function.
The changelog also lists changes that can affect existing code:
- A warning for the pattern of a spread and a variable in a
caseclause, such as[..x] -> x, a syntax that it says “may be removed in a future (major) release”. - Deprecation of matching on bit array patterns that contain empty string segments.
- A new unreachable-pattern warning when an earlier clause matches an overlapping string, with the changelog noting that “Code that previously compiled cleanly may now emit this warning.”
- Renaming of Erlang type definitions called
Recordtorecord_, so as not to overwrite Erlang’s built-inrecordtype introduced in OTP29.
Patch Release 1.19.1
The v1.19.1 changelog is dated 2026-10-07 and lists one bug fix: the export javascript-prelude and export typescript-prelude commands would not run. The 1.19.0 blog post describes these commands as gaining the ability to write to a file, so the fix concerns a command area touched in 1.19.0.
What We Don’t Know
The sources reviewed do not give figures for the compile-time improvement in text, and the benchmark is the project’s own. No independent measurement of the new code generator was among the sources. The blog and the changelog show slightly different JavaScript snippets for the pattern-matching example, so the exact generated output should be checked against the compiler directly.