Behaviour for persisting feature flags outside of the ETS cache.
The Botica.Flags.Store GenServer uses the configured persistence
adapter as the source of truth at boot (load_all/0) and writes
through on every mutation (save_flag/1, delete_flag/1). The ETS
table remains the in-memory read cache: O(1) reads without a
GenServer round-trip.
Built-in adapters
Botica.Flags.Persistence.Disk— atomic JSON file (default,~/.botica/flags.json)
Custom adapters
defmodule MyApp.FlagPersistence do
@behaviour Botica.Flags.Persistence
@impl true
def load_all, do: {:ok, []}
@impl true
def save_flag(_flag), do: :ok
@impl true
def delete_flag(_name), do: :ok
endConfigure the active adapter in :botica application env:
config :botica, :flags_persistence, [
adapter: MyApp.FlagPersistence,
opts: []
]
Summary
Callbacks
Removes a flag from the persistent store.
Loads every persisted flag. Called once at Store boot to populate the
ETS cache. Returns {:ok, [Flag.t()]} or {:error, term()}.
Persists a single flag. Called on every Store mutation.
Functions
Returns the configured persistence adapter from application env.
Defaults to Botica.Flags.Persistence.Disk with no options.
Disables persistence entirely (adapter: false). The Store then behaves
as a pure in-memory registry — useful for tests and ephemeral processes.
Callbacks
Removes a flag from the persistent store.
@callback load_all() :: {:ok, [Botica.Flags.Flag.t()]} | {:error, term()}
Loads every persisted flag. Called once at Store boot to populate the
ETS cache. Returns {:ok, [Flag.t()]} or {:error, term()}.
@callback save_flag(Botica.Flags.Flag.t()) :: :ok | {:error, term()}
Persists a single flag. Called on every Store mutation.
Functions
Returns the configured persistence adapter from application env.
Defaults to Botica.Flags.Persistence.Disk with no options.
Configuration
config :botica, :flags_persistence, [
adapter: Botica.Flags.Persistence.Disk,
opts: [path: "/var/lib/botica/flags.json"]
]
@spec enabled?() :: boolean()
Disables persistence entirely (adapter: false). The Store then behaves
as a pure in-memory registry — useful for tests and ephemeral processes.
config :botica, :flags_persistence, adapter: false