Vault is a lightweight Elixir library for immutable data storage within a process subtree.
Due to Elixir's actor model nature, it's common for a process to have global context that is valid for every function call inside of the process and its children.
For example, this context can include:
- A user when processing a user's request
- A tenant in a multi-tenant application
- Rate limiting buckets/quotas
- Cache namespaces
- API or client versions
- And many more, depending on your application domain
Vault.init/1
provides you a guarantee that the context can only be defined once per existing process subtree, so you won't override it by accident. This makes it easy to reason about your context origination.
# Initialize vault in parent process
Vault.init(current_user: %{id: 1, first_name: "Alice", role: "admin"})
# Access data from any descendant process, even these not linked!
spawn(fn ->
Vault.get(:current_user) # => %{id: 1, first_name: "Alice", role: "admin"}
Vault.init(current_user: :user) # => raises, because the ancestor already has vault initialized
end)
# Access data from the parent process itself
Vault.get(:current_user) # => %{id: 1, first_name: "Alice", role: "admin"}
However, if for some reason you need to split initializations, you can use Vault.unsafe_merge/1
, but the immutability is no longer guaranteed.
- Instead of property-drilling context data through every function call, Vault provides access to shared data across your process tree. When used for immutable data - this is a cleaner and more maintainable approach, simplifying cognitive load when reasoning about your code.
- The data is initialized only once and is immutable (unless you explicitly call
unsafe_*
functions). - The API mirrors Elixir's
Map
module for familiar data access.
- This library relies on the
ProcessTree
library by JB Steadman, which does all the heavy lifting of traversing process trees and propagating data back. You can read more about how ancestors are fetched in this amazing blog post by the library's author.
def deps do
[
{:vault, "~> 0.2.1"}
]
end