# Eco 0.2.0 released

**URL:** <https://discourse.elm-lang.org/t/eco-0-2-0-released/11067>\
**Category:** Show and Tell\
**Created:** [November 10, 2026, 3:51pm UTC](https://discourse.elm-lang.org/t/eco-0-2-0-released/11067 "2026-11-10T15:51:07Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [November 10, 2026, 3:51pm UTC](https://discourse.elm-lang.org/t/eco-0-2-0-released/11067/1 "2026-11-10T15:51:07Z")

</div>

A new release of _eco_ compiler and runtime for building native applications in Elm is available:

> **[Release v0.2.0 · eco-lang/eco-compiler](https://github.com/eco-lang/eco-compiler/releases/tag/v0.2.0)**
>
> Stable release v0.2.0.
> 
> Commit: 208a501d81ddf3aab19d8bbe21bd1f8123b785f3
> Built: 2026-11-09 22:12:46 UTC
> 
> SHA256SUMS
> 6188f934163d6f7de73acf3141dd2081f7bd2b98dfe9bd40617920b0e3f0043e eco-0.2.0-arm64...

> **[Getting started - eco Docs](https://eco-lang.org/docs/getting-started/)**
>
> How to install the eco 0.2.0 nightly release on Linux, macOS or Windows, build the hello world example, and write a first eco/system program.

### What is eco ?

eco is Elm Compiler Optimized, a compiler that aims to be 100% Elm compatible and can compile Elm code to run natively on x86 or Arm platforms, supporting Linux, Mac and Windows.

### What is new in this release ?

All of the elm/\* packages are ported, with their kernels re-implemented in C++.

There is an official system package providing support for lots of Posix-ish APIs, as well as for running web servers, including the server end of websockets.

> **[eco/system - eco Packages](https://eco-lang.org/packages/eco/system/)**
>
> POSIX-style system programming for eco programs

This also has Streams over the same Bytes type as elm/bytes for streaming IO.

The Streams concept and many parts of the eco/system package were copied from Gren with permission from Robin Heggelund Hansen.

### How does this release improve on 0.1.0

The 0.1.0 alpha release was less mature, and IO could only be done through its exposed internal compiler API eco/kernel, which was never intended to be a public API.

The 0.2.0 release is a significantly better compiler and runtime:

- Overall performance was improved roughly 4x.
- The garbage collector was greatly improved, with a tenured nursery, and concurrent mark and sweep, much better pause times, and most GC work kept off the main program thread.
- Some formal verification work was done on the threaded GC by modelling it in TLA+
- Compile times are better, although there is still work to be done here.
- A significant new compiler optimization called Lambda Set Substitution was introduced, which eliminates most dynamic dispatches for higher order function calls.
- Many smaller optimisations added.

### What can I do with it ?

You can build server side applications, talking HTTP or Websockets or raw TCP or UDP, TLS is also supported. I have built a game server that serves the game over HTTP or Websockets for example.

You can build native applications with ports, and use that mechanism to implement any kind of native application you wish. Zero-copy Bytes over ports is supported with an API in C++ that helps to eliminate common mistakes.

You can re-use existing Elm code and packages to do this.

### Does it do reference counting or optimistic mutation ?

No, the heap is only garbage collected in 0.2.0. Functional-but-in-place optimisation will be the subject of a later release.

### So how fast is it really ?

> **[Performance - eco Docs](https://eco-lang.org/docs/performance/)**
>
> Measured run times of eco's native code against stock Elm's JavaScript, including the workloads where eco is slower, plus how fast the compiler builds itself and how short its garbage-collector pauses are, with how each was measured.

The benchmark results are not spectacular overall, yielding roughly a 1.6x speed up compared with Javascript running on Node, generated with Elm 0.19.1, but there is a clear trend in those results.

Benchmarks that do not use kernel functions and are compute oriented, speed up maybe 5x to 10x over JS. Benchmarks using kernel functions do less well, and are even slower in some cases.

The reason for poor kernel function performance is partly that little effort has gone into optimizing them yet, and that most optmizations do now flow accross from Elm into C++. For example, a C++ kernel function cannot be inlined into Elm code.

This will be addressed in later releases, with kernel functions becoming part of ecos MLIR dialect, or by compiling the C++ into LLVM IR and then optimizing all the LLVM IR together. The MLIR dialect route will make use of MLIR as templates, allowing monomorphization, inlining, lambda sets and other optimizations to flow accross the kernel boundary.

### What other exciting features are in the pipeline ?

- Support for multi-threaded Elm with actor model concurrency.
- A reflection API built on runtime type information. (RTI already exists to allow Debug.log to know how to print any value given to it.)
- A formal language specification and conformance test suite.
- A package server for sharing packages that build on eco/system and that acts as a mirror of [https://package.elm-lang.org/](https://package.elm-lang.org/) for redundancy when GitHub fails.
- Porting of all of the elm-explorations/\* packages.

### Where can I learn more ?

The roadmap is up to date with my current thinking at this time.

> **[Roadmap](https://eco-lang.org/roadmap/)**
>
> Track the evolution of eco from first commit to stable release.

The code is documented with a Program Theory, Peter Naur style, and much of that has been written up in the Docs section on the website, start here:

> **[A tour through the compiler - eco Docs](https://eco-lang.org/docs/tour/)**
>
> One small Elm program followed through every stage of eco, from source and type checking through monomorphization, MLIR and lowering to a running native executable, with the real compiler output at each step.

---

<div class="post-metadata">

**Author:** ![nicholasevans](https://avatars.discourse-cdn.com/v4/letter/n/8edcca/32.png) [@nicholasevans](https://discourse.elm-lang.org/u/nicholasevans)\
**Post date:** [November 10, 2026, 5:53pm UTC](https://discourse.elm-lang.org/t/eco-0-2-0-released/11067/2 "2026-11-10T17:53:05Z")

</div>

The jump from exposing internal compiler APIs to a proper eco/system package with POSIX-style support is the part that stands out to me. Having Streams built over the same Bytes type as elm/bytes should make streaming IO feel consistent rather than bolted on. The tenured nursery and concurrent mark and sweep also sound like a real step up in pause behavior, not just raw throughput. Curious whether the C++ kernel reimplementations of the elm/\* packages introduce any subtle differences in behavior compared to the JavaScript originals.

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [November 10, 2026, 10:06pm UTC](https://discourse.elm-lang.org/t/eco-0-2-0-released/11067/3 "2026-11-10T22:06:16Z")

</div>

> [@nicholasevans](#):
>
> Curious whether the C++ kernel reimplementations of the elm/\* packages introduce any subtle differences in behavior compared to the JavaScript originals.

They almost certainly do. To give one example, in eco:

```auto
modBy 0 2 == 0 -- Not a runtime error as in Elm 0.19

```

A significant difference is that eco has Int as 64-bit Ints. You generally will not have a problem using Ints to count things, as Elms 53-bit Ints can count a long way. Bitwise operations in Elm only work on the first 32-bits, which means that when you use the full width of an Int as in hashing or random number generators, you will see differences in behaviour. You can mask off the bottom 32-bits to recover the same behaviour between eco and Elm.

The site I put up with an Elm test suite will quantify the difference exactly, and help to figure out where eco needs a bit of adjustment to make it match Elm, modulo different Int implementation and some bug fixes.

The good news is, that most of the difference is in the corner cases, it is overall quite usable as it stands.

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [November 11, 2026, 2:57pm UTC](https://discourse.elm-lang.org/t/eco-0-2-0-released/11067/4 "2026-11-11T14:57:55Z")

</div>

> <https://github.com/eco-lang/eco-compiler/blob/lib-max-spike/spikes/max/mnist/src/MnistNet.elm>

To get you excited about the kinds of things that eco can enable, here is an example of doing machine learning, on a GPU, from Elm.

I pulled together this spike linking Elm to Max, Modulars compute graph engine that compiles to GPUs and other AI accelerators. To do this I had to rebase eco onto LLVM 26, from 24, so that it uses the same LLVM version as Max. This enabled using the binary format for the MLIR code it exchanges with Max through its `mo` dialect.

Then I built a nice DSL that lets you construct a compute graph over Tensors, with auto differentiation, and define its training step and eval function. As you can see in the example, the code is really nothing more than a textbook description of a neural net in the format of the DSL, which has been designed to present this cleanly.

The output graph can then be trainined on Max, and used to classify the MNIST hand-written character data set - a machine learning classic.

I am not compiling Elm code itself to Max, only the DSL. But with the “reification” techniques, this too would be possible. For example you could compile a pure Elm function over Floats, Vectors or Tensors, and actually run it on a GPU. We could have:

```auto
fun : Float -> Float 
fun = ...

Tensor.map fun tensor

```

And really run `fun` on the GPU, compiled from Elm code.

Just a spike for now, but I wanted to share this with you because this is the sort of thing I am building eco to eventually be able to do, and I think it will bring Elm into new domains of operation where strict typing, nice DSLs and builder patterns and so on are often lacking. It explains why MLIR was a deliberate choice for intermediate IR for eco too! And it is an exciting direction to consider going in.
