elixir.menuAn Optimum Tech project

01 / STARTING POINTS

What are you building?

Phoenix is our first choice for web applications. A CLI, library or device starts elsewhere.

Web application or APIBrowser products, customer portals and HTTP APIs.PhoenixLiveView for interactive screens

Starting point

Use Phoenix for routing, controllers and web application conventions. Add LiveView for server-driven interactive screens; an API-only product does not need a browser UI.

mix phx.new my_web_app

Account for

Choose persistence from the product's needs. PostgreSQL + Ecto is our recommendation for shared relational web data, not a prerequisite for every Elixir program. Review generator options for API-only or database-free applications.

Command-line toolDeveloper tools, local automation and terminal applications.Mix + OptionParser

Starting point

Keep command parsing separate from the modules that perform the work. OptionParser handles flags; the application owns help text, subcommands, output and exit codes.

mix new my_tool

Account for

An escript needs Erlang/OTP on the target machine. Evaluate Burrito when distributing a bundled executable to users without that runtime, and test each supported OS and architecture.

LibraryReusable modules used by other Elixir applications.Mix

Starting point

Define a small public module API, examples and tests. Generate documentation with ExDoc; publish to Hex if the package is intended for reuse outside the project. Add a supervision tree only if the library owns long-lived processes.

mix new my_library

Account for

Choose supported Elixir/OTP versions and dependency constraints for consumers. A library does not need an HTTP server or database unless that is its purpose.

Background serviceWorkers, integrations and processes that keep running.Mix + OTP supervision

Starting point

Use supervision for process lifecycles and recovery. Keep calculations and business operations in ordinary modules; introduce stateful processes where they are needed.

mix new my_service --sup

Account for

Supervision does not persist work. Choose durable storage or a queue when recovery requires it. Add Plug + Bandit for a small HTTP interface if needed; use Mix releases for deployment.

Data analysis or machine learningNotebooks, data transformations and numerical models.Livebook; Mix for the application

Starting point

Use Livebook for interactive exploration, Explorer for tabular data, and Nx for numerical computation. Add Axon when defining or training neural networks is the requirement. Move reusable work into a Mix application when it needs a maintained API, tests or a service lifecycle.

Account for

Hosted model calls, local inference and training are different requirements. Check native backends, memory and hardware before selecting a deployment environment.

Embedded deviceHardware products, sensors and deployed Linux devices.Nerves

Starting point

Start from the Nerves installation and project guides for the target hardware. Build firmware with the system and libraries that the device requires.

Account for

Hardware support, firmware updates and access to the device determine the setup. A web interface can be added when useful; it does not define the device application.

Audio or video systemStreaming, transcoding and realtime media processing.Membrane + an OTP application

Starting point

Build media pipelines with the source, processing and output elements needed for the product. Phoenix may provide a separate control interface if there is a web UI.

Account for

Protocols, codecs and native dependencies determine the pipeline and deployment. Ordinary file uploads do not require a media framework.

Checks for every Mix project

Use mix format for formatting, compile with warnings as errors, and test behavior with ExUnit. Add Credo for useful static feedback. Use Boundary when domains or layers need enforced module dependency rules; declare allowed dependencies and exports, enable its Mix compiler, and fail CI on violations. Keep the same checks in local work and CI.

04 / OPTIONAL TOOLS

Libraries for the features you need.

Choose these when the product needs them. Each entry explains the use case, how it fits, and the additional setup.

Accounts and product controls

Social login and OIDCAssent

Use it when

Users need to sign in with Google, GitHub, Apple or an OpenID Connect provider.

How it fits

Integrate provider authentication with the application's existing accounts and sessions.

What else to account for

Account linking, session management and permissions remain application concerns. SAML is a separate requirement.

Rate limitingHammer

Use it when

Login attempts, API calls, uploads or expensive actions need limits.

How it fits

Define limits by actor, operation and time window; choose a backend that matches the deployment.

What else to account for

A node-local counter does not automatically enforce a cluster-wide quota. Choose the algorithm's burst behavior deliberately.

Feature flagsFunWithFlags

Use it when

Features need gradual rollout, per-customer access or an operational off switch.

How it fits

Choose an Ecto or Redis persistence adapter and configure synchronization between nodes.

What else to account for

Keep permission checks separate from rollout flags. Remove expired flags and restrict the management interface.

Files and documents

Object storageExAws.S3

Use it when

Uploads need to live in an S3 or compatible object store.

How it fits

Use ExAws with its S3 service module for object operations and signed URLs. In a LiveView app, connect it to the upload flow.

What else to account for

The storage service, credentials, access rules and lifecycle policy are separate. Check which operations a compatible service actually supports.

Image processingImage

Use it when

The product needs thumbnails, resized uploads, image conversion or watermarks.

How it fits

Process images through the libvips-backed Image API; use Oban for work that needs retries.

What else to account for

Vix/libvips introduces native runtime requirements. Check the deployment target and required codecs, and limit input dimensions and processing work.

Markdown parsing and renderingMDEx

Use it when

The application needs CommonMark parsing, rendered Markdown content or transformations over a Markdown document tree.

How it fits

Use MDEx to parse and transform a document or render HTML. Choose extensions and syntax highlighting deliberately; reserve HEEx components and expressions for trusted application-owned content.

What else to account for

Treat user-authored Markdown as untrusted input: configure and verify HTML sanitization, link handling and size limits. Never evaluate its HEEx expressions. MDEx uses native Rust code; verify precompiled artifact support or a Rust build toolchain for the deployment target.

PDF generationChromicPDF

Use it when

Invoices, reports or other HTML documents need downloadable PDFs.

How it fits

Render application-owned HTML and CSS through a managed Chrome process.

What else to account for

Chrome is an additional runtime dependency; PDF/A conversion also uses Ghostscript. Isolate rendering and control access to external resources.

CSV import and exportNimbleCSV

Use it when

Users need bulk uploads, data exports or integrations through CSV files.

How it fits

Parse and write streams; validate each imported row through the application's business rules.

What else to account for

CSV parsing does not validate field types or business rules. Define malformed-row handling and spreadsheet formula escaping for exports.

APIs and collaboration

Documented HTTP APIsOpenApiSpex

Use it when

External consumers need an OpenAPI contract for the Phoenix API.

How it fits

Describe operations and schemas, validate requests, and test responses against the specification.

What else to account for

A schema does not enforce ownership or authorization. Keep the published contract aligned with application behavior.

GraphQL APIsAbsinthe

Use it when

Clients specifically need GraphQL queries, mutations or subscriptions.

How it fits

Expose the existing business layer through a schema; use Dataloader where batching is needed.

What else to account for

Resolvers still need authorization and query-cost limits. Ordinary JSON endpoints remain simpler when GraphQL adds no client benefit.

Who is onlinePhoenix Presence

Use it when

Chat, collaborative screens or live rooms need connected-user state.

How it fits

Track presence metadata and broadcast joins and leaves through Phoenix's existing realtime infrastructure.

What else to account for

Presence is ephemeral and eventually consistent. It is not a durable audit trail, access-control system or editing-conflict resolver.

Languages, locales and money

Translated interface textGettext

Use it when

The application needs interface copy in multiple languages.

How it fits

Use the Gettext integration already present in typical Phoenix projects; maintain translation catalogs and plural forms.

What else to account for

It does not translate user-authored content automatically. Dates, amounts and units need locale-aware formatting too.

Localized dates and numbersLocalize

Use it when

Dates, numbers, currencies and units must follow the user's locale.

How it fits

Use CLDR-based formatting and parsing. For new projects, evaluate Localize as the documented successor to the ex_cldr family.

What else to account for

Existing ex_cldr applications need a planned migration. Check runtime requirements and package locale data for deployment.

Currency amountsMoney (ex_money)

Use it when

Prices, invoices or balances need explicit currencies and decimal arithmetic.

How it fits

Represent amount and currency together and make rounding rules explicit.

What else to account for

This is not payment processing, tax calculation or an accounting ledger. The package is ex_money; check its major-version migration notes.

AI features

Calling language modelsReqLLM

Use it when

The product needs text generation, streaming, structured outputs, embeddings or model tool calls through supported provider APIs.

How it fits

Use a common Elixir interface to supported providers, including schema-constrained output and embedding generation. Keep provider-specific settings explicit; store embeddings separately when retrieval needs persistence.

What else to account for

Provider and model capabilities differ. Start here for direct model calls; add an agent framework only when orchestration needs it. Define application validation, permissions and representative evaluations separately.

Tool-using AI agentsJido.AI 2.x

Use it when

A language model must select tools, keep agent state or run a bounded multistep reasoning loop.

How it fits

Add Jido.AI to a Jido agent and use ReqLLM for provider access. Define tools as actions, and keep model selection, timeouts and tool policy explicit.

What else to account for

Model output is untrusted and nondeterministic. Restrict tool permissions and side effects, set cost and step limits, require approval for high-risk operations, and test representative tasks.

Validated structured extractionInstructorLite

Use it when

The main requirement is extracting typed fields from text into Ecto schemas, with casting, validation and retries.

How it fits

Define an instruction with an Ecto schema and use changeset validation to check the returned fields. Choose this alternative when its Ecto integration fits better than ReqLLM structured output.

What else to account for

It is not an agent runtime and does not provide response streaming. Valid fields can still contain incorrect facts; handle failed validation, retry limits and domain checks explicitly.

Conversational chains and tool loopsLangChain for Elixir

Use it when

The application is organized around message history, model responses and chained tool calls, or already uses the Elixir LangChain abstractions.

How it fits

Compose messages, model adapters and tools through LLMChain. Use its callbacks for streaming and inspect tool-call trajectories when evaluating a conversation workflow.

What else to account for

This is an alternative orchestration approach, not an extra layer every ReqLLM or Jido application needs. Bound tool loops, authorize actions and implement persistence and retry behavior for the actual product.

AI features for Ash applicationsAsh AI

Use it when

An application already uses Ash resources and needs to expose selected actions as model tools or MCP tools, generate structured outputs or maintain embeddings.

How it fits

Add Ash AI to the existing Ash domains and resources. Select the actions to expose and carry the authenticated actor and tenant into their execution; configure model access only for features that require it.

What else to account for

Choose Ash as an architecture first. Ash AI does not justify migrating an ordinary contexts application by itself. Test authorization for every exposed action and verify embedding updates, retrieval quality and model costs.

Running pretrained modelsBumblebee + Nx

Use it when

Inference should run on infrastructure you control, using a supported pretrained model.

How it fits

Load supported model architectures with Bumblebee and serve predictions through Nx.Serving.

What else to account for

Plan model memory, a suitable numerical backend and hardware. Model compatibility and licensing need to be checked individually.

Data processing and machine learning

Message ingestion pipelinesBroadway

Use it when

The application consumes a stream from Kafka, RabbitMQ, SQS or another supported source.

How it fits

Build concurrent processing stages with batching, acknowledgements and back-pressure.

What else to account for

The source connector determines delivery behavior. Keep handlers safe to retry; ordinary application jobs still fit Oban.

Tabular data analysisExplorer

Use it when

Imports, analytics or reports need dataframe transformations over CSV, Parquet or similar datasets.

How it fits

Use typed series and dataframes for grouping, joining and transforming tabular data.

What else to account for

The default Polars backend uses native code. Check deployment support and memory use; routine application queries still belong in Ecto.

Building and training neural networksAxon + Nx

Use it when

The project needs to define or train a neural network in Elixir rather than only run a supported pretrained model.

How it fits

Use Axon to build models and training loops on Nx, with a numerical compiler/backend suited to the target hardware. Use Bumblebee when loading a supported pretrained model meets the requirement.

What else to account for

Check native backend support, hardware, memory and training data. Validate on held-out data and measure deployment behavior; adding Axon does not establish model quality or a performance advantage.

Performance and scaling

Custom demand-driven pipelinesGenStage

Use it when

Producers and consumers need a custom event pipeline with demand-driven backpressure.

How it fits

Model stages around runtime concurrency and data transfer; keep business steps in functions.

What else to account for

You own buffering, subscriptions and failure behavior. Use Task.async_stream for simpler bounded parallel work, or Broadway for its ingestion features.

Parallel dataset transformationsFlow

Use it when

A large enumerable needs parallel mapping, partitioned grouping, aggregation or windows.

How it fits

Build a Flow pipeline and choose partition keys, stages and windows for the workload.

What else to account for

Coordination has overhead; small inputs can favor Enum or Task. Partitioning affects grouping and order; bound accumulating state.

Compare code performanceBenchee

Use it when

A measured hot path has alternative implementations to compare.

How it fits

Benchmark representative inputs with warmup, runtime, memory and reduction measurements.

What else to account for

Microbenchmarks do not establish application throughput or production latency. Check correctness and end-to-end behavior separately.

Locate runtime bottlenecksMix + OTP profilers

Use it when

The application is slow and you need to locate expensive calls or repeated work.

How it fits

Use the supported mix profile task or OTP profiler for the question; combine findings with the existing Telemetry events.

What else to account for

Check installed runtime support for tprof, eprof and fprof. Tracing can change timing and add overhead; profile a representative bounded workload.

Managed in-memory cachingCachex

Use it when

A node-local cache needs expiration, eviction or fallback loading beyond a small ETS implementation.

How it fits

Configure cache limits, expiration and loading behavior around the data lifecycle.

What else to account for

Define invalidation and stale-data policy. A local cache is not a durable source of truth or a cluster-wide consistency guarantee.

Native computation and Rust integrationRustler

Use it when

Profiling identifies CPU-heavy work suited to native code, or the product must call an existing Rust library.

How it fits

Expose a narrow NIF interface and select normal versus dirty scheduling appropriate to the work.

What else to account for

Native faults can crash the VM. Validate target builds, scheduler impact and boundary-copying costs; consider a separate OS process when fault isolation is required.

Compiled tensor computationEXLA + Nx

Use it when

Nx numerical work needs a compiled backend on supported CPU or accelerator hardware.

How it fits

Use EXLA as the Nx compiler/backend and select the supported target, precision and memory settings.

What else to account for

Compilation, data transfer and native dependencies have costs. Verify hardware/toolchain support and measure representative workloads; it is not a general accelerator for arbitrary Elixir functions.

Elastic remote executionFLAME

Use it when

Bursty expensive work should run on additional ephemeral nodes, such as media processing or model inference.

How it fits

Configure a bounded runner pool and an appropriate backend. Start only required application children and size runner database pools deliberately.

What else to account for

Boot latency, network transfer and capacity costs matter. FLAME supplies compute execution, not a durable job queue; pair it with Oban when jobs must persist.

Development tools

Module dependency rulesBoundary

Use it when

Domains or layers need explicit, compiler-checked dependencies and public module exports. Useful for agent-maintained applications as well as human-maintained code.

How it fits

Declare each boundary in its root module with use Boundary, explicit deps and a small exports list. Add the compile-time dependency and compiler below. A boundary always exports its root module; prefer explicit exports over exports: :all. Keep allowed calls aligned with the architecture.

What else to account for

Violations are compiler warnings unless compilation uses --warnings-as-errors. External OTP application calls are allowed by default; opt into selected app checks or strict mode when required. Dynamic calls such as apply/3 are not checked. Boundary enforces static module references; it does not isolate an agent’s files, processes or network access. Libraries can limit the compiler to dev/test as the compiler documentation describes.

Set it up

# In mix.exs deps/0:
{:boundary, "~> 0.11", runtime: false}

# In mix.exs project/0:
compilers: [:boundary] ++ Mix.compilers()

# In each domain root module (adapt the names):
use Boundary, deps: [MyApp.Accounts], exports: []

Run mix deps.get, then mix compile --warnings-as-errors in the environments your CI checks. Add a temporary forbidden static call to confirm the check fails, remove it, and rerun successfully. The dependency alone does not enforce boundaries.

AI-assisted Phoenix developmentTidewave

Use it when

A coding agent needs runtime context from a Phoenix application during development.

How it fits

Add the Tidewave Phoenix integration as a development-only dependency and plug. Connect your coding agent to inspect logs, evaluate code, query the development database and read installed-version documentation.

What else to account for

This gives the agent access to the running development application. Use a trusted local environment and keep the dependency and endpoint out of production; this is tooling for building the app, not an AI feature for its users.

A different application architecture

Declarative business applicationsAsh

Use it when

Resources, actions, policies and derived APIs form a substantial part of the application.

How it fits

Evaluate Ash early as the domain layer beneath Phoenix, with only the extensions the product needs.

What else to account for

This changes how business logic is modeled. It is an architectural choice, not a small utility to install beside an unchanged contexts design.

Stateful agent workflowsJido 2.x

Use it when

The application needs cooperating agents that choose or coordinate steps, share reusable actions and react to routed signals.

How it fits

Model the system with agents, actions, signals and directives, and run long-lived agents through Jido's supervised runtime. AI is optional; add Jido.AI only when decisions need a language model.

What else to account for

Prefer a plain GenServer, durable Oban jobs or an explicit function pipeline when behavior is fixed and simple. Supervision and in-memory state alone do not preserve progress across restarts; choose and verify persistence and resume behavior.

Specialist projects

These need their own architecture and deployment plan:

  • Nerves — Embedded devices and firmware.
  • Membrane — Audio, video and streaming pipelines.

05 / THE THINKING

Defaults with reasons.

The application decides the architecture.

A command-line tool can start with Mix and OptionParser. A long-running service needs a supervision tree. A browser product benefits from Phoenix. These are different starting points within the same ecosystem.

Mix project types

Keep Phoenix’s conventions where they fit.

For web apps, use Phoenix, LiveView, contexts and Ecto as the foundation. Keep the generated HTTP server, asset pipeline and test setup.

Phoenix generator documentation

Decide on Ash early.

Contexts and Ecto are our default. Choose Ash when a resource-and-action model, policies and generated APIs fit the domain. It affects how the application is structured, so evaluate it before building out the data layer.

How Ash models an application

A dependency still needs integration.

Oban needs database migrations and workers. Swoosh needs a delivery adapter. File uploads need storage and access rules. Every recommendation includes the remaining setup and the limits of the choice.

06 / FOR AGENTS

Start with the requirements.

Read the existing project, choose an application path, and use the relevant reference. Do not install the whole menu.

Dependency guidance for agents

Use usage_rules in any Mix project to collect dependency-authored instructions and find documentation. Follow the project’s existing conventions for where agents read guidance, keep Phoenix’s generated guidance when using its default setup, and refresh dependency rules when versions change.

usage_rules documentation
01

Read the existing project

First read https://elixir.menu/agents.md for direct Markdown and JSON retrieval. In the application, start with README.md, mix.exs, mix.lock and runtime pins. Preserve its architecture and follow its maintained workflow. Do not regenerate an existing project.

02

State the application requirements

Identify the interface, whether work must keep running, persistence needs, and deployment target. Choose one of the starting points above; a product may combine more than one. Do not assume Phoenix or PostgreSQL.

03

Check the environment

Check elixir --version and mix --version. Follow the official Elixir installation guide if prerequisites are missing; respect existing version management. Install a web generator, database or specialist toolchain only for the selected path.

04

Generate in an empty destination

Use the selected starter and its current documentation. The commands above are scaffolding examples, not complete applications. For the Phoenix web path, follow setup.md; for Nerves and Membrane, follow their own project guides.

05

Select libraries by requirement

Read runtime.md for built-in state, concurrency and storage choices. Read optional.md and add only tools whose use cases match the product. Check versions, native dependencies and deployment constraints. Record the reasons and setup in the project’s maintained documentation. Preserve its existing agent-guidance conventions.

06

Verify the actual application

Run formatting, compilation and relevant tests. Exercise the real interface: CLI help, output and exit codes; service startup and recovery; HTTP behavior; or the target device. Verify the packaged artifact on the intended target and report what remains untested.

Phoenix + LiveView setup recipe

For a new web application with PostgreSQL. Check the current generator and supported runtime versions before running these steps.

Verified 6 October 2026 on macOS: Phoenix 1.8.15, LiveView 1.2.12, Elixir 1.20.4 / OTP 29.1.1 and PostgreSQL 18.3. Setup, auth migrations, formatting, compilation, 112 generated tests and four HTTP routes passed. Browser flows and production deployment remain untested.

01

Check the machine and the destination

Read the project README and runtime configuration if they exist. Confirm the operating system, intended app name and destination. Check the tools below; a missing command identifies a prerequisite to install. Do not generate into a directory containing unrelated work.

elixir --version
mix --version
mix phx.new --version
psql --version

Check: Record the detected versions and missing tools. A PostgreSQL client version does not prove that a database server is running or accessible.

02

Install missing prerequisites

Use the official Elixir instructions for the detected operating system and a compatible Erlang/OTP version. Reuse the machine’s existing runtime manager. Install and start PostgreSQL using its operating-system-specific instructions. Linux development also needs inotify-tools for live reload. After Elixir is working, install missing Mix tooling and the Phoenix generator with the commands below. Respect any existing version pins; these unversioned commands are for a fresh setup.

mix local.hex
mix local.rebar
mix archive.install hex phx_new

Check: Record the selected versions in the project’s runtime configuration. Verify the application can connect to PostgreSQL using the intended local credentials before creating databases.

03

Generate the application

Replace my_app with the agreed application name. Keep Phoenix’s LiveView, mailer, asset and agent-guidance defaults. Respect the project’s established documentation conventions.

mix phx.new my_app --database postgres
cd my_app

Check: Configure the new application’s local database connection before running mix setup. Keep private credentials out of source control. Accept dependency installation when the generator prompts, or let mix setup fetch them.

04

Set up the database and assets

Run this from the generated application directory, after configuring PostgreSQL. The generated setup task fetches dependencies, prepares the database and builds the development assets. Read its definition in mix.exs before using it in an existing application.

mix setup

Check: Setup must finish successfully. If a step fails, fix the reported prerequisite and resume from that step; do not regenerate over the application.

05

Add accounts if the product needs them

For first-party user accounts, generate Phoenix authentication with the LiveView option. Skip this step for an application without accounts. Follow any additional instructions printed by the generator.

mix phx.gen.auth Accounts User users --live
mix deps.get
mix ecto.migrate

Check: Review the generated account flows and authorization boundaries. Configure email delivery before relying on production magic links.

06

Verify and hand off

Format the generated code and any local configuration changes, then run the checks. Start the development server using the project’s normal process. Open the printed URL and verify the page loads. If accounts were generated, exercise registration and sign-in with development email.

mix format
mix format --check-formatted
mix compile --warnings-as-errors
mix test
mix phx.server

Check: Report exact versions, the app location, startup URL, checks that passed and anything unverified. Keep README.md and mix.lock current. Do not describe the setup as production-ready or benchmarked.