Elixir Persistent Term
A persistent term is a value stored once in a global store and read from any process. It suits configuration that is read often and written rarely.
Store a setting and read it back
Put a map of settings under one key. Get returns the same map.
:persistent_term.put(:app_settings, %{mode: :fast, retries: 3})
IO.inspect(:persistent_term.get(:app_settings))A missing key takes a fallback
Get with two arguments returns the fallback for a missing key. Erase removes a key, so a later get takes the fallback too.
:persistent_term.put(:feature_flag, :on)
IO.inspect(:persistent_term.get(:feature_flag, :off))
:persistent_term.erase(:feature_flag)
IO.inspect(:persistent_term.get(:feature_flag, :off))Every process reads the same stored value
A spawned process reads the stored value and sends it home. The parent prints the value the child read.
:persistent_term.put(:greeting, "hello")
parent = self()
spawn(fn ->
value = :persistent_term.get(:greeting)
send(parent, {:read, value})
end)
receive do
{:read, value} -> IO.inspect(value)
endExample
:persistent_term.put(:limits, %{max_items: 10, timeout: 30})
:persistent_term.put(:limits, %{max_items: 25, timeout: 30})
parent = self()
spawn(fn ->
limits = :persistent_term.get(:limits)
send(parent, {:limits, limits.max_items})
end)
receive do
{:limits, max_items} -> IO.puts("max_items: #{max_items}")
end
fallback = :persistent_term.get(:missing_limits, %{max_items: 10, timeout: 30})
IO.puts("fallback_max: #{fallback.max_items}")Key points
- Persistent term: a global store reached through :persistent_term.
- Use :persistent_term.put/2 to store a value under a key.
- Use :persistent_term.get/2 to read a value or take a fallback when the key is missing.
- Use :persistent_term.erase/1 to remove a key from the store.
- A stored value is visible to every process in the same runtime.
In this example, the limits map is stored, then stored again with a larger max_items value, so the second put replaces the first. A spawned process reads the stored map and sends its max_items value home, and the parent prints 25. A get for a key that was never stored returns the fallback map, whose max_items value prints as 10.
Note
writes copy the value for all readers, so the store suits data that changes rarely, not a value that changes on every request.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Which call reads the stored value for :limits, or returns %{max_items: 10} when :limits was never stored?