# 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](guides/guarantees.md) — if
you read one page to decide on Fief, read that one.
```elixir
# 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}
```
```elixir
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
- [Overview](guides/overview.md) — what Fief is, when to use it, and when
the AP tools are the better answer (often).
- [Guarantees](guides/guarantees.md) — the contract, scope conditions
included.
- [Getting started](guides/getting-started.md) — deps to first `call`
round-trip.
- [The key lifecycle](guides/key-lifecycle.md) · [Using
Fief.Cache](guides/cache.md) — the two surfaces.
- [The netsplit matrix](guides/protocols/netsplit-matrix.md) — every
partition, what callers observe, and the deterministic test that
reproduces it.
Rendered docs live on [hexdocs.pm/fief](https://hexdocs.pm/fief) once
published; until then, `mix docs` builds the same site locally.
## Installation
```elixir
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.