ETS, DETS, :persistent_term & Mnesia
Table types: :set, :ordered_set, :bag, :duplicate_bag.
36.1 ETS — Erlang Term Storage (in-memory, concurrent tables)
Table types: :set, :ordered_set, :bag, :duplicate_bag. Access: :public, :protected (default; owner writes, all read), :private. Tables are owned by a process and deleted when the owner dies — own tables from a long-lived supervised process (or use the heir option).
:ets.fun2ms/1 (via Ex2ms library in Elixir) builds match specs from functions.
table = :ets.new(:users, [:set, :public, :named_table, read_concurrency: true])
:ets.insert(:users, {1, "Ann", 30})
:ets.insert(:users, [{2, "Bob", 25}, {3, "Eve", 35}])
:ets.lookup(:users, 1) # [{1, "Ann", 30}]
:ets.member(:users, 2)
:ets.delete(:users, 2)
:ets.update_counter(:counters, :hits, 1, {:hits, 0})
:ets.tab2list(:users)
:ets.match(:users, {:"$1", :"$2", 30}) # [[1, "Ann"]]
:ets.select(:users, [{{:"$1", :"$2", :"$3"}, [{:>, :"$3", 26}], [:"$2"]}]) # names where age > 26
:ets.info(:users), :ets.delete(:users)36.2 DETS — disk-based ETS
Limited to 2 GB per file; no ordered_set.
{:ok, t} = :dets.open_file(:store, file: ~c"store.dets", type: :set)
:dets.insert(t, {:k, :v}); :dets.lookup(t, :k); :dets.close(t)36.3 :persistent_term — read-optimized global constants
Extremely fast reads; updates are expensive (global GC scan). Use for rarely-changing config.
:persistent_term.put({MyApp, :config}, %{a: 1})
:persistent_term.get({MyApp, :config})36.4 :atomics and :counters
ref = :counters.new(1, [:write_concurrency])
:counters.add(ref, 1, 1); :counters.get(ref, 1)36.5 Mnesia
A distributed, transactional database built into OTP; stores Erlang terms, supports replication across nodes, RAM or disk tables.
Libraries: memento (Elixir wrapper), amnesia.
:mnesia.create_schema([node()])
:mnesia.start()
:mnesia.create_table(Person, attributes: [:id, :name, :age])
:mnesia.transaction(fn -> :mnesia.write({Person, 1, "Ann", 30}) end)
:mnesia.transaction(fn -> :mnesia.read({Person, 1}) end)