DocsHex.pm

PhoenixGenApi

A framework for rapidly building backend APIs on top of Phoenix Channels and Erlang clustering. Define your business logic on any node — the framework handles routing, validation, permissions, retries, and observability. No HTTP endpoints to write, no routes to configure, no restarts to deploy.

Version: 2.18.0 | Elixir: ~> 1.18 | OTP: ~> 27 | License: MPL-2.0

Why PhoenixGenApi?

Traditional Phoenix backends require you to: define routes, write controllers, serialize responses, handle errors, and restart to deploy changes. PhoenixGenApi eliminates all of that:

How It Works

┌──────────┐ WebSocket ┌──────────────────┐ RPC ┌──────────────┐
│ Client │ ◄──────────────► │ Phoenix Gateway │ ◄─────────► │ Service Node │
└──────────┘ (Phoenix Ch.) │ (uses this lib) │ (Erlang) │ (your app) │
└──────────────────┘ └──────────────┘
  1. Clients send requests through a Phoenix Channel.
  2. The Gateway looks up the matching FunConfig, selects a node, validates arguments & permissions, then executes the remote function.
  3. The Service Node runs the function and returns the result.

Service nodes can register new APIs at any time — the gateway picks them up automatically (pull) or receives them immediately (push).

Features

FeatureDescription
Dynamic ConfigurationAdd, update, or remove APIs at runtime from any cluster node
Response ModesSync, async, streaming, and fire-and-forget
Node SelectionRandom, hash-based, round-robin, sticky, or custom strategies
Function VersioningRun multiple API versions side-by-side; enable/disable per version
Rate LimitingSliding-window rate limiter with global and per-API limits
PermissionsAuthenticated-only, argument-based, role-based, or custom callback
RetryConfigurable retry on same node or across all nodes, with exhaustion telemetry
Hooksbefore_execute / after_execute callbacks with per-hook timeout protection
Relay MessagesGroup-based message relaying with automatic cleanup on disconnect
Circuit BreakerPool-level and worker-level circuit breakers
Telemetry31 events across 5 categories for observability
SecurityAdmin gate, push tokens, MFA allowlist, payload size limits

Installation

def deps do
[
{:phoenix_gen_api, "~> 2.16"}
]
end

Use :libcluster to form the Erlang cluster.

Documentation

GuideDescription
Getting StartedBuild a working API gateway in 10 minutes with a Phoenix gateway and service node
Step-by-Step GuideEvery feature explained with copy-paste code examples: validation, permissions, rate limiting, async, streaming, hooks, relay, security, telemetry
FunConfig ReferenceField-by-field reference for the central configuration struct
ConfigurationFull configuration reference: gateway, rate limiter, worker pool, security
ArchitectureDeep dive into the supervision tree, request lifecycle, config management, execution engine, and all subsystems
Execute FlowLine-by-line walkthrough of the complete request execution path with file references
Relay MessagesComplete reference for group-based messaging: group types, permission matrix, process monitoring
TelemetryFull event reference, integration patterns, Telemetry.Metrics examples, and best practices

Quick Start

Define your API on the service node:

defmodule MyApp.Api do
def get_user(user_id) do
%{id: user_id, name: "Alice"}
end
end

Create a FunConfig and register it on the gateway (pull mode):

# On the service node — define a supporter
defmodule MyApp.GenApi.Supporter do
def get_config(_arg) do
{:ok, [%PhoenixGenApi.Structs.FunConfig{
request_type: "get_user",
service: "user_service",
nodes: [Node.self()],
mfa: {MyApp.Api, :get_user, []},
arg_types: %{"user_id" => :string},
response_type: :sync
}]}
end
end
# On the gateway — configure the puller
config :phoenix_gen_api, :gen_api,
service_configs: [%{
service: "user_service",
nodes: [:"app@host"],
module: MyApp.GenApi.Supporter,
function: :get_config,
args: []
}]

Add PhoenixGenApi to your Channel:

defmodule MyAppWeb.ApiChannel do
use Phoenix.Channel
use PhoenixGenApi, event: "api"
end

Call from the client:

{
"service": "user_service",
"request_type": "get_user",
"request_id": "req_1",
"args": { "user_id": "123" }
}

That's it — you have a working API gateway. See the Getting Started guide for the full 2-node walkthrough.

IEx Helpers

PhoenixGenApi.rl_status("user_123") # Rate limit status
PhoenixGenApi.rl_global() # Global rate limits
PhoenixGenApi.rl_config() # Rate limiter config
PhoenixGenApi.cache_status() # Config cache status
PhoenixGenApi.pool_status() # Worker pool status
PhoenixGenApi.pushed_services_status() # Pushed services status
PackageDescription
PhoenixGenApiCore library — dynamic API gateway over Phoenix Channels
EasyRpcWrap RPC calls from remote nodes so they can be used like local functions
ClusterHelperDynamic cluster node discovery
ToonExTOON encoder/decoder — compact binary protocol for Phoenix Channels
AshPhoenixGenApiAsh extension that auto-generates FunConfig from Ash resources

AI Agent Support

mix usage_rules.sync AGENTS.md --all --link-to-folder deps --inline usage_rules:all
mix tidewave

Connect at http://localhost:4114/tidewave/mcp. See Tidewave for details.