Real-world Erlang & Elixir library audits, performance benchmarks against Dialyzer, and deep-dives into abstract interpretation and type inference on OTP 29.
Case Studiesbenchmarks2026-11-13· Manuel RubioOTP 29
Replacing Dialyzer and Eqwalizer with Prisma: 15 contract bugs and 4 oxbow parameters resolved in RabbitMQ's consensus engine
In this case study, we examine the complete modernization of ra, the open-source Raft consensus engine implemented in pure Erlang by the RabbitMQ team at Broadcom. ra is the foundational core behind RabbitMQ Quorum Queues, Stream engines, and Khepri metadata coordination.With 55 BEAM modules coordinating complex distributed state machines, asynchronous write-ahead logs (WAL), snapshotting, and leader elections, ra is one of the most critical and battle-tested distributed systems libraries in the BEAM ecosystem.We replaced both Dialyzer and Eqwalizer with Prisma, eliminated over 250 lines of static-typing workarounds and stubs, generated portable .pplt contract tables, and resolved 15 contract bugs and 4 dead parameters caught by Prisma's hybrid analyzer. All changes have been submitted upstream in rabbitmq/ra#677.
Inside Prisma's hybrid type algebra, forward constraint inference, widening bounds, PropEr semantic proofs, and mutation benchmarks
After publishing Understanding Prisma PPLT, two sharp questions quickly came up on Erlang Slack—asking less about packaging and caching, and more about the heart of any static analyzer: what type reasoning does Prisma actually use, how does it ensure correctness, and does it handle modern OTP features like nominal types and native records?
What PLT stands for, why Dialyzer's Persistent Lookup Tables struggle in modern workflows, and how Prisma PPLTs solve them
In the BEAM ecosystem, static typing and contract checking have long revolved around a central acronym: PLT, which stands for Persistent Lookup Table. Introduced over two decades ago with Dialyzer, the PLT was a breakthrough mechanism that enabled success typings to be saved on disk rather than recomputed from scratch on every run.Yet in today's software engineering reality—dominated by containerized CI/CD pipelines, package managers like Hex.pm, ephemeral build workers, and monorepos—Dialyzer's traditional PLT has become one of the most frustrating bottlenecks in Erlang and Elixir workflows.
Auditing a 49-module pure Erlang PHP interpreter: 59 bugs and contract discrepancies caught in 0.51s
In this third and culminating chapter of our ephp ecosystem audit series (following ezic and zucchini), we turn our attention to the core application itself: ephp, a 100% pure Erlang implementation of the PHP interpreter.With 49 BEAM modules spanning lexing, parsing, runtime stack management, memory and object heaps, and extensive standard library modules (pcre, date, math, file, string, spl), ephp represents a non-trivial, battle-tested Erlang codebase.This case study details the modernization of ephp 0.3.3, the removal of legacy dependencies, the benchmark against Dialyzer on OTP 29, and how Prisma uncovered 59 contract discrepancies and real runtime edge-case bugs that Dialyzer had ignored for years.
Inferring exact AST types across leex and yecc parsers where Dialyzer goes blind
In this second case study of the ephp dependency audit series, we analyze zucchini, the Erlang INI file parser used by ephp to load php.ini configuration files. While small in module count (3 BEAM modules: zucchini, zucchini_lexer, and zucchini_parser), zucchini exposes a classic blind spot in Erlang static analysis: code generated by leex (lexical analyzer generator) and yecc (LALR-1 parser generator).
Performance, CPU efficiency, and bug detection comparison between Prisma and Dialyzer
In this case study we analyze ezic, the IANA timezone handling library used by ephp. ezic is a particularly demanding and representative test case because it combines 10 core logic modules with 469 automatically generated modules (one for each timezone in the IANA database, plus link and map indexes), totaling 479 BEAM modules.