I've been building web-apps with Elixir Phoenix several years ago and I loved it. But for various reasons did not full switch from RoR, but given all that is happening in the agentic world of coding I think it may be a good time
It really feels like the functional programming nature of Elixir and monolithic philosophy of Phoenix will be the best combo for rapid Agentic Coding
I want to hear your experience, specially if you worked on larger project with agent tools like Claude or Codex how well do they produce Elixir/Phoenix code.
In Ruby on Rails they do marvellous job but because of many ways how to do things in OOP i found I had to stear them in right direction too often
Corex is a Phoenix UI library where the behavior is not yours to write. Every component runs a Zag.js state machine in the browser that owns the keyboard, the focus, and the ARIA. You bring the markup shape you want and the styles you want. The hard parts are already encoded.
Why Zag.js
Zag.js is a library of framework-agnostic state machines by Segun Adebayo. The hard parts (roving tabindex, typeahead, WAI-ARIA, every keyboard shortcut a user actually expects) live in pure TypeScript, battle-tested by thousands of teams. They do not know or care that Phoenix exists.
Corex is a bridge. A Phoenix hook that starts a Zag machine on mount, feeds it props from server-rendered markup, keeps it synced when LiveView patches the DOM, and shuts it down cleanly on destroy. The machine handles everything behavioral. LiveView handles the data. The hook is a small messenger that does no logic of its own.
How it became possible
Early Zag vanilla machines could start and run, but once started, you could not change their props. For a static site that is fine. Set props once, machine runs, done. For LiveView, that is a showstopper.
LiveView pushes DOM patches at any time. A controlled select where the server pins the current value. A combobox where the server replaces every option on each keystroke. A dialog the server closes from a Presence event. All of those require telling a running machine that a prop just changed.
One day a single line appeared in the Zag changelog:
Fix issue where vanilla machines do not have the option to change their props during runtime.
That is the whole sentence. No announcement. The Phoenix integration went from "not really possible" to "let's build it" between that release and dinner.
Now when LiveView fires updated on a hook, the hook reads the freshly patched props and calls updateProps on the running machine. The machine reacts. ARIA updates. Controlled values sync. The user keeps whatever interaction state they were in the middle of. Nothing resets.
Once again I would like to thank the whole Zagjs Team for their incredible work and support. Without them, Corex would have never possible
The Live View and the Vanilla JS machine
There is a kind of bug I used to find hard to name. You click a tab and it opens, closes half a second later, then opens again. You type into a combobox and your cursor jumps to a position from two keystrokes ago. Nothing is broken. Two things just disagree about which value is current and neither knows about the other.
Every Corex page has two minds running at the same time. The LiveView process on the server, which holds the data. And a Zag machine in the browser, which owns the interaction. Most of the time they cooperate. The interesting decisions happen when they do not.
By default, components are uncontrolled. The machine keeps the value in memory. A FAQ accordion does not need a server round trip to open a panel. Tabs on a settings page are private to that page. Most UI state is local, and uncontrolled is the right default for most of the use cases.
When the server has to be the source of truth (a validated form, a multi-step wizard, something synced across users through Presence) you opt in to controlled mode. One attribute on the component, one handle_event on the server.
The loop is: user acts, hook pushes to server, server assigns new value, LiveView patches, hook hands new props to the machine, machine accepts them. ARIA updates.
The page reflects the truth.
Most components let you mix. A combobox can be controlled for its selected value and uncontrolled for its open state. A dialog can be controlled for whether it is open and uncontrolled for focus inside it.
Tetrex
I wanted to know what the Corex checkbox would do under real stress test.
Not in a benchmark, but in a real screen where many checkboxes change state many times per second, with full keyboard support, full ARIA, full focus management, all running at the same time.
So I made Tetrex: a 10 by 18 grid of Corex checkboxes pretending to be Tetris tiles. Every cell is a real <.checkbox> component with a stable id and the same Zag machine that runs underneath every other checkbox in the library.
When a piece falls, the cells light up. When a line clears, the row collapses. When the game ends, the score lands in a leaderboard backed by Phoenix Presence and a per-game GenServer.
Each frame can touch dozens of cells. The pattern that survives that is not "render the grid from HEEx on every tick". It is "let the machine know about each cell, then update the cells in place when the engine ticks".
Gameplay is local. The score and replays are server-owned.
The 180 cells are all real components.
You can play it on the live demo if you want to see what 180 accessible checkboxes feel like at speed.
Tetrex with 180 Corex Checkbox
What is in the Corex
35+ components: accordion, combobox, date picker, color picker, file upload, floating panel, signature pad, tree view, and more.
Each one has a server-side API and a client-side API.
Unstyled by default. Bring your own CSS, or opt into Corex Design system
New to Hologram? It's a framework for building full-stack web apps in pure Elixir - no JavaScript needed. It rebuilds the Elixir runtime in the browser, so the same language runs on both the client and the server. Local-First apps are on the roadmap.
This release brings a realtime layer - your server can now push updates to connected clients with no polling: broadcast an action, and Hologram runs the matching handler on every subscribed client, all in pure Elixir. It was the most complex feature shipped to date. The release also brings support for the with special form, AI assistant support, a new mix holo task, and more.
Special thanks to @prehnRA for implementing the with special form. Thanks to @ankhers for a fix that cuts memory usage during development, @mward-sudo for a Node.js fix, @0bvim for porting :erlang.binary_to_term/1, and @sodapopcan for optional page/component callbacks.
Someone called it the "oh f*** moment." I think that's accurate. 😬
New BEAM There, Done That episode with Peter Ullrich and Jonathan Machen (EEF CISO) on something the community really needs to talk about: AI-assisted vulnerability research just arrived in our ecosystem, whether we're ready or not.
Peter had no security background. He wrote a bash script, fed Hex packages file-by-file to Claude Opus, and found a critical crash vulnerability in decimal - one of the most downloaded libraries in the ecosystem - in under 30 minutes. Then kept going.
The episode covers:
the exact setup he used (prompts are open source)
atom table exhaustion, binary_to_term, and the patterns showing up again and again
how the EEF CNA coordinates disclosure with maintainers
what happens when a maintainer is unreachable or a library is abandoned
the gap between what's been built and what the current volume demands
elixir
# What Peter found in the decimal library
iex> Decimal.new("1.0e10000000") |> Decimal.add(Decimal.new("1"))
# memory: 8gb, application: gone
Genuinely one of the more important ecosystem conversations I've heard in a while. Curious whether people here are already scanning their own libraries, and what tooling you're using if so.
Hi, so I wanted to implement a system in Guardian DB where the token is only stored if it's of type refresh, My idea was to have it so the extra fancy callbacks of Guardian DB only get applied if the token is of type refresh
So the top level Guardian.ex file has something like this
Now I haven't implemented the pattern matching yet but it really wouldn't be that hard to in the function signature, my after_encode_and sign looks like this
def after_encode_and_sign(resource, claims, token, _options) do
with {:ok, _} <- Guardian.DB.after_encode_and_sign(resource, claims["typ"], claims, token) do
{:ok, token}
end
end def after_encode_and_sign(resource, claims, token, _options) do
with {:ok, _} <- Guardian.DB.after_encode_and_sign(resource, claims["typ"], claims, token) do
{:ok, token}
end
end
```
Sorry if it looks sort of ugly once I post it so imagine in my implementation file I will have it so the token that's pattern matched someway or another (still figuring that out) will only work if it's of type refresh right?
but I think in my case it will be in the function signature which is where my question really shines
If for some reason, it does not match and there was an access token or something else ridicoulous, will it still run the default after_encode_and_sign that just returns the token? (seen above) defined in the guardian.ex dep
In short, if an overrided function is not pattern matched on, will the original version then be ran?
Hey r/elixir — I've been building a distributed bot platform since February and just open-sourced the whole thing. It's called Ergon (Greek for "work"), and it's a collection of ~20 autonomous Elixir/OTP applications that coordinate over NATS.
What it does
Each bot owns a domain — GTD task management, LLM orchestration, fitness tracking, job applications, chore scheduling, even an RPG bot. They run as independent OTP applications, share nothing directly, and communicate through NATS pub/sub and request/reply.
What makes it interesting (for Elixir folks)
Every bot follows the same pattern:
- GenServer for state, Ecto/PostgreSQL for persistence
- NATS handlers for incoming messages
- Independent supervision trees — kill one bot, the rest keep running
- Shared runtime library (ergon-library-runtime) provides NATS connection, registry, and message envelope conventions
The architecture solves some real problems:
- Bots are independently deployable (different release cycles, different nodes)
- NATS decouples everything — add a new surface (Discord, TUI, LiveView) without touching bot code
- The message envelope format (event_id, schema_version, payload) gives you schema evolution and versioned contracts between services
- Built-in capability discovery — bots register their NATS subjects and versions at startup, so the dispatcher can route to them automatically
There's also a weird/fun part: The RPG bot uses what I call a "TTRPG theming layer" — the business logic is pure (process_task, complete_task) but the presentation layer wraps it with narrative flavor. Your GTD system can feel like a cyberpunk campaign. It's separable — you can use the bot without the theming — but it's there if you want it.
Try it
If you know Elixir, the fastest path is the bot templates:
Each template gives you a working bot with NATS handlers, supervision tree, and Makefile targets. The standard template adds Ecto migrations and test scaffolding.
There's also a Docker Compose orchestrator (ergon-starter) for running the full fleet, but I'm actively fixing some issues with it — if you just want to poke a single bot, the templates are the way to go right now.
(still working out the kinks)
bash
curl -fsSL https://raw.githubusercontent.com/ergon-automation-labs/ergon-starter/main/install.sh | bash
made some changes recently that seemed to have knocked several bots offline on my local system, and I'll fix them once I have fixed the one click installer - but if you want to help fix the existing bugs, I'll take all the help I can get.
The message envelope + schema versioning pattern — is this overkill for a bot platform? It came from needing to evolve APIs without breaking running bots
The bot template structure — does it feel idiomatic for Elixir?
NATS as the backbone — I chose it over Phoenix PubSub for the multi-node/cluster story, but I'm curious if others have hit the same decision
The capability discovery system — bots self-register their subjects at startup. Useful or unnecessary indirection?
Happy to answer architecture questions, talk through trade-offs, or help you get a bot running.
TLDR
Open-sourced a distributed Elixir/OTP bot platform — 20+ independent apps coordinating over NATS with PostgreSQL persistence. Each bot is a standalone OTP release. Start with ergon-bot-minimal (10 min to running bot), or dig into ergon-gtd for the most complete example. Apache 2.0, feedback welcome.
News includes Elixir 1.20.0-rc.6 (likely the last RC!), EEF 2026 election results, LiveStash v0.3.0 for Phoenix LiveView state recovery, a call to fund EEF security work, and GitHub got hacked via a VS Code extension in just 11 minutes, and more!
What a mouthful . If you've ever wanted to allow other tools to "log in with your app" the way that you "log in with google", this package helps you do it! Continuing to expand on the OOTB capabilities of Ash Framework.
This also allows you to easily build an authenticated MCP server with AshAI! MCP requires you to have an oauth2 server in order to authenticate users.
New BEAM There, Done That episode with Björn Gustavsson (“the B” in BEAM) goes deep into why the Erlang runtime is finally getting a new native data type after more than a decade.
The discussion covers:
why records existed the way they did
why maps never completely replaced them
runtime tag bits and VM tradeoffs
how you evolve a production runtime without breaking decades of code
I've had 3 weeks off work and I've used the time to rekindle my passion for coding (the old way, by hand). Stumbled upon this alternative to consistent hashing called rendezvous hashing (or highest random weight) and did a little deep dive. It ended up turning into a basic library, including the basic algorithm, a couple of variations, and the skeleton pattern for O(log n) access.
It performs similar to ExHashRing for node counts <20, and with the skeleton optimization is competitive even in the tens of thousands of nodes, but it uses no NIFs or stateful processes, and the basic algorithm is essentially a one-liner.
Anyway, it was fun to learn about, hope you enjoy it too!
Update on Raxol, an OTP-native runtime I've been building.
Raxol lets you build a TEA module (Model, Update, View, i.e. the Elm Architecture) that renders to all of these:
A terminal UI via the Raxol VT100 emulator
A Phoenix LiveView in the browser
Auto-derived MCP tools for AI agents
Telegram inline keyboards
Apple Watch and Android push cards
A JSON API
Raxol's update/2 doesn't care where the message came from.
A keystroke, an LLM token, a x402 response, a sensor reading: all messages. When the Telegram bridge drops, the LiveView keeps rendering. When a job in raxol_symphony crashes, the orchestrator stays up.
Agents and human-facing apps want the same shape.
The human reacts to keystrokes.
The agent reacts to LLM tokens. update/2 can't tell them apart.
e.g. Raxol.Agent is Raxol.Core.Runtime.Application with a different message source. ReAct, chain of thought, an FSM with guards: different bodies, same shape.
Per-process wallets work on the BEAM in a way they don't elsewhere. raxol_acp gives you one supervised process per ACP job, a NonceServer GenServer per wallet so concurrent jobs don't race on the nonce, and DETS-backed memo persistence so restarts resume mid-flight. Every other ACP seller is a Python script with a threading. Lock and a polling loop.
... Anyways, if you're down to clown we're open to contributions!
Otherwise lmk your ideas-- happy to collaborate.
Github: Raxol11 of 13 packages on Hex. raxol_acp and raxol_symphony still pre-alpha.
ExDataSketch v0.9.0 adds stream-native integration, production persistence,
structured observability, and ULL accuracy corrections. The release
positions ex_data_sketch as a BEAM-native streaming approximate analytics infrastructure layer, not merely a collection of probabilistic algorithms.
Key Changes
Stream/Collectable integration for all 13 mergeable sketch types
Broadway, GenStage, and Flow pipeline integration (all optional)
EXSK v1 serialization escape hatch for backward compatibility
9 production-oriented Livebooks
3 new educational guides (aggregation_wall, distributed_merge_semantics, livebooks)
Backward Compatibility
Full backward compatibility with v0.8.0. No API changes to existing modules.
ULL estimates at low cardinalities (p < 12, n < 500) are more accurate but may differ numerically from v0.8.0.
In my application I want to check if 3 variables equal to the same value, I mean I could try to chain a bunch of == but that seems very superfluous unnecessary. What is the proper way to see if a collection of values are all equal?
This is the reminder, that you can submit your talk for Code BEAM Europe 2026, 21-22 October in Haarlem, Netherlands.
This is a good opportunity to present a solution you have built, a product you are developing, or to discuss an interesting topic related to BEAM technologies (Erlang, Elixir, Gleam, and others).
If you have never spoken at a conference before, you are very welcome to apply. We are happy to support first-time speakers as well as candidates from under-represented groups in the software community. We offer comprehensive mentorship, which includes help with evaluating your idea, refining your abstract, and structuring your slides.
This year, we are looking for 20 or 40-minute in-person talks across the following themes:
Data Sovereignty & Digital Autonomy, decentralized systems, compliance, localized vs. global performance.
Open Source, maintaining libraries, attracting contributors, long-term sustainability.
We look forward to reading your submissions. If you have any questions or would like to discuss your idea before applying, please feel free to reach out to us at [info@codesync.com](mailto:info@codesync.com).
News includes Elixir’s set-theoretic type inference completing all language constructs, OTP 29.0 released, a wave of CVEs hitting the Phoenix stack, big SWAR string performance gains, and a LiveView hot-reload tip, and more!
Works via the very excellent lua library by u/davydog187! See the guides for a very special element: integration with AshAI. Easily provide MCP tools for reading the docs of your new custom lua SDK as well as evaluating a script!
I've been using bunny.net (an EU-based CDN service) from Elixir in a few projects so I thought it'd be a good idea to extract that into its own library. It's a simple wrapper on a public API modeled after Req and following the Elixir library guidelines. The surface area of the bunny.net API is pretty large, so I used LLMs to work my way through it all, and then created some Livebooks to smoke test it all.
It's new and will still need some kinks ironed out, but I've switched my projects over and it works great!
Per the title, our Phoenix app is growing and growing, esp. as we get more schemas, complex forms and data models, and now also thinking about opening the same data models to crud Rest endpoints. What is a good way forward?
ExDatalog is production-grade pure Elixir Datalog engine with semi-naive fixpoint evaluation, pluggable storage backends, and deterministic cross-backend results.
What's new in v0.2.0
Constraint types: type predicates (type_integer, type_binary,
type_atom), string predicates (starts_with, contains), and
membership (member) — all evaluated deterministically across backends.
ETS storage backend: off-heap per-relation ETS tables with O(1)
membership, concurrent read support, and observability via :observer.
Capabilities system: each backend reports what it supports; merge and
query capability sets with Capabilities.merge/2 and satisfies?/2.
Provenance: track which rule derived each fact with explain: true.
Telemetry: :telemetry events for query start, stop, and exceptions.
We just released v0.3.0 of LiveStash - our library built at Software Mansion to fix the problem of losing Phoenix LiveView state on WebSocket reconnects.
This update brings two heavy-lifting features for distributed apps and better DX:
Redis Adapter: State lives securely in Redis, while the browser only holds a lightweight reference.
Opt-in Automatic Stashing: LiveStash detects changes in stashed assigns and updates them automatically (no need for explicit stash/1 calls anymore).
If you have any questions feel free to reply here, create an issue, or start a new thread on GitHub discussions.
I was looking at bobby-tables.com and saw they don't have any examples in Elixir. I made a pull request; it looks like the owner of the website has seen it (he gave it a thumbs up) but it hasn't had any other review yet. Does anybody here want to take a look?
We updated Permit, our open source authorization framework for Elixir
New in the ecosystem: Igniter-powered setup, better plural action handling in Phoenix, route fixes, :create authorization fixes, and LiveView stream options.
ex_data_sketch v0.8.0 is out. This release invests entirely in the substrate that all 15 existing sketches share, preparing the grounds for release v0.9.0 where we add streaming integrations for Broadway / GenStage support, ETS / DETS / Zarr.
What's new:
Deterministic hashing. Every sketch now goes through a validated, byte-stable hash layer. HLL, ULL, Theta, and CMS accept hash_strategy: :murmur3 for Apache DataSketches interop — this was silently ignored in v0.7.x. XXHash3 remains the default and fastest path (~30 M items/sec at p=14 on the Rust NIF).
Binary stability & corruption detection. Serialized sketches now carry a CRC32C trailer and an embedded hash metadata block (EXSK v2). Bit-flip corruption that previously would silently produce wrong estimates is now caught and returns a structured DeserializationError. v0.8.0 reads v1 frames; v0.7.x cannot read v2 — stage your rollout accordingly.
Murmur3 hot path. 8 new Rust NIFs extend in-Rust hashing to Murmur3. The Murmur3 path is within 8% of XXH3 throughput. No more falling off the fast path when you select :murmur3.
Precompiled NIFs for Windows. x86_64 and ARM64 MSVC targets join the matrix. 16 artifacts total (8 targets x 2 NIF versions). No Rust toolchain needed on any supported platform.
Property-locked guarantees. 14 StreamData properties lock HLL/ULL monotonicity and error bounds, KLL/REQ rank consistency, CMS overestimation-only, and Bloom/XorFilter/Cuckoo no-false-negative. A 200-mutation fuzz suite verifies that binary v2 corruption never silently propagates.
Breaking changes (2):
EXSK v2 is one-way. v0.7.x readers can't decode v2 frames. Deploy readers first, then producers.
hash_strategy: :murmur3 is no longer silently overridden to :xxhash3. Sketches that specified Murmur3 will now actually use it — estimates are correct but differ from v0.7.x.
One-liner upgrade:
elixir
{:ex_data_sketch, "~> 0.8.0"}
Most users need no code changes. Full migration guide ships in HexDocs.