Fief

CP key ownership for Elixir clusters: at most one node owns a given key at any instant, in every failure mode.

The Elixir ecosystem is rich in AP distribution primitives — Horde, Swarm, syn — that resolve conflicts after both sides of a partition have acted. Fief is, roughly, "Horde, but CP": keys hash to partitions, partition ownership lives in a small arbiter (Postgres, in the shipped adapter — infrastructure you already run, not a consensus cluster to operate), every node holds a TTL lease and stops serving itself before anyone may take over. When forced to choose, keys go unavailable rather than doubly owned.

Two surfaces share that substrate: Fief.Key backs each key with a process — lifecycle callbacks, state that follows ownership, fencing policy — and Fief.Cache is a partitioned single-owner cache — coherent get/put/delete, at most one writer per key. The headline contract: routing single-ownership is unconditional; state and side-effect single-ownership holds under the default fencing mode; there are no delivery guarantees, ever; and it scales in keys (millions), not nodes (tens). The exact scope conditions are in the guarantees — if you read one page to decide on Fief, read that one.

# in your supervision tree — the instance is the coordination domain
{Fief,
name: MyApp.Fief,
authority: {Fief.Authority.Postgres, repo: MyApp.Repo},
vnode_impl: {Fief.Key.VnodeImpl, []},
partitions: 1024,
lease_ttl: 5_000}
defmodule MyApp.Session do
use Fief.Key # on_fence: :terminate — the mode that upholds the guarantee
@impl true
def init(user_id, :fresh, _ctx), do: {:ok, MyApp.Sessions.load(user_id)}
def init(_user_id, {:residual, session}, _ctx), do: {:ok, session}
@impl true
def handle_message({:touch, at}, _from, session),
do: {:reply, :ok, %{session | last_seen: at}}
@impl true
def extract_state(session), do: {:ok, session}
end
MyApp.Session.call(MyApp.Fief, user_id, {:touch, DateTime.utc_now()})
# {:ok, :ok} — served by the one live process for user_id, wherever it lives

Documentation

Rendered docs live on hexdocs.pm/fief once published; until then, mix docs builds the same site locally.

Installation

def deps do
[
{:fief, "~> 0.1.0"}
]
end

Requirements: Elixir ~> 1.20 and Erlang/OTP 28+ (the Fief.Key layer uses EEP 76 priority messages for the transfer freeze advisory; enforced at instance boot). The Postgres adapter uses your app's Ecto repo via optional dependencies — Fief itself has no hard dependency on Ecto.