Staff-Level Elixir
Distilled staff-level judgment for Elixir on the BEAM — the design decisions Elixir, OTP, Ecto, and Phoenix force, and how an experienced engineer settles them, written so an agent applies them while writing or reviewing code. Each rule corrects a specific wrong default; there is no rule for things the model already gets right (syntax, basic idioms, the standard library).
When to Apply
- Writing or reviewing OTP code — deciding whether something needs a process, and which (GenServer, Task, Agent, ETS, supervisor)
- Handling failure — choosing between tagged tuples, exceptions,
with, and letting a process crash - Writing Ecto — queries, associations, transactions, changesets, large result sets
- Building Phoenix controllers and LiveViews — context boundaries, socket state, mount lifecycle
- Running concurrent work — parallel fan-out, fire-and-forget tasks, handling untrusted input
- Any request to make Elixir code more idiomatic, more fault-tolerant, or "staff-level"
Rule Categories
| # | Category | Prefix | Covers |
|---|---|---|---|
| 1 | Process & OTP Design | otp- |
Whether a problem needs a process, and which one; supervision |
| 2 | Error Handling & Let-It-Crash | err- |
Signalling failure; when to raise, rescue, or crash |
| 3 | Idioms & Design Choices | data- |
Pattern matching, Stream/Enum, iolists, pipes, macros |
| 4 | Concurrency & the Scheduler | conc- |
Bounded/isolated parallelism; atom-table safety |
| 5 | Ecto & Data Access | ecto- |
N+1, atomic writes, constraint races, large sets |
| 6 | Phoenix & LiveView | phx- |
Context boundaries, socket memory, mount lifecycle |
Quick Reference
1. Process & OTP Design
otp-genserver-not-default— a GenServer is a serialization point, not the default abstractionotp-ets-for-shared-reads— read-heavy shared state belongs in ETS, not behind a GenServer.getotp-supervise-over-manual-restart— child specs + DynamicSupervisor/Registry, not hand-rolled restart logicotp-handle-continue-init— defer heavy startup tohandle_continue;init/1blocks the supervisor
2. Error Handling & Let-It-Crash
err-tagged-tuples-vs-raise—{:ok/:error}for expected failures, raise only for invariant violationserr-let-it-crash— don't rescue to mask bugs; let the supervisor restart clean stateerr-with-happy-path— chain fallible steps withwith; keep the error term intact
3. Idioms & Design Choices
data-pattern-match-over-conditionals— function clauses + guards over if/cond on argument shapedata-stream-vs-enum— Stream for large/lazy/early-exit, Enum for small concrete listsdata-iolists-over-concat— build large output as iolists;<>in a loop is O(n²)data-pipe-idioms— pipe a data subject through transformations, not to save a variabledata-functions-over-macros— solve it with a function before reaching for a macro
4. Concurrency & the Scheduler
conc-async-stream-bounded—Task.async_streamwithmax_concurrency+ explicittimeoutconc-task-supervised-nolink— supervised, unlinked Task for fire-and-forget workconc-atom-exhaustion— never build atoms from external input; useto_existing_atom
5. Ecto & Data Access
ecto-preload-n-plus-one— preload up front, never inside an Enum loopecto-multi-for-transactions—Ecto.Multifor atomic multi-step writes with failure attributionecto-db-constraints-over-validation— DB constraint +unique_constraint, not a racy validation queryecto-stream-large-sets—Repo.stream/batch large sets;Repo.allOOMs at scaleecto-atomic-counters—update_allwithinc:for counters; read-modify-write loses updates
6. Phoenix & LiveView
phx-context-boundary— web layer calls contexts, never Repo or schemas directlyphx-liveview-streams— streams for large/growing collections, not full lists in assignsphx-mount-twice-connected— gate side effects onconnected?/1; mount runs twice
How to Use
Read a reference file when its decision comes up. Each rule names the wrong default it corrects, then shows the canonical way (with an incorrect/correct contrast only where the wrong way is a real trap).
- Section definitions — category structure and ordering
- Rule template — for adding new rules
- AGENTS.md — auto-built table of contents across all rules
Reference Files
| File | Description |
|---|---|
| references/_sections.md | Category definitions and ordering |
| assets/templates/_template.md | Template for new rules |
| metadata.json | Version and source references |