sullyMusty
Active Memory - A Simple ORM for ETS and Mnesia
active_memory is a package to help bring the power of in memory storage with ETS and Mnesia to your Elixir application.
ActiveMemory provides a simple interface and configuration which abstracts the ETS and Mnesia specifics and provides a common interface called a Store.
Downloads have exceeded 200,000 thus seems prudent to check in on it. Updated for changes in newer versions of Elixir and ran security checks and scans to ensure it is safe – all good!
Most Liked
sullyMusty
Hi all
— a big update since I first announced ActiveMemory here.
v0.7 is now on Hex, and it’s grown from a simple ORM into a typed, attribute-queryable in-memory store for ETS and Mnesia — with the safety rails you’d want before trusting it with short-lived or sensitive data. Four highlights:
Atomic, take-once
withdraw/1
withdraw/1now fetches-and-deletes in a single atomic operation —:ets.select_delete/2for ETS, a:mnesia.transaction/1for Mnesia. Under concurrent access exactly one caller gets a given record; everyone else gets{:error, :not_found}. Great for one-time tokens and job-claim patterns:{:ok, token} = TokenStore.withdraw(%{value: submitted_token})
TTL / record expiry
Give a table a
ttland its records expire automatically:defmodule MyApp.Tokens.Token do use ActiveMemory.Table, type: :ets, ttl: :timer.hours(1) attributes do field(:value) field(:user_id) end endEnforcement is hybrid: a lazy read-filter means
one/select/all/withdrawnever return an expired record (exact and immediate), and a periodic sweep deletes them to reclaim memory (sweep_intervalconfigurable, default 60s). Zero overhead for tables without attl.
Crash resilience (TableHeir)
An ETS table is owned by the process that creates it, so a
Storecrash used to mean losing the data. ActiveMemory now runs a tiny, stable heir process registered as the ETS:heir; on a crash the table transfers to it, and the restartedStorereclaims it — data intact. No configuration, no API change. (Mnesia tables were never affected — they already survive process crashes.)
ActiveRepo — multiple tables, one process
For several tables under one supervised entry point:
defmodule MyApp.Repo do use ActiveMemory.ActiveRepo, tables: [MyApp.People.Person, MyApp.Tokens.Token] end MyApp.Repo.write(%Person{first: "Kara"}) # table inferred from the struct MyApp.Repo.one(Token, %{value: raw}) # reads take the table explicitlyIt’s named
ActiveRepo(notRepo) so it won’t collide with yourEcto.Repo, and a single repo can mix ETS and Mnesia tables — each with its ownttlif you like.Where it fits
ActiveMemory isn’t a cache — if you want key-based caching with eviction and hit/miss stats, Cachex and Nebulex are excellent. ActiveMemory is for structured records in memory that you query by their attributes:
SessionStore.select(%{user_id: user_id, active?: true}) StaffStore.select(match(:role == "admin" and :last_login < cutoff))…the kind of query a key/value store can’t express without hand-rolled secondary indexes.
A note on concurrency
A question that came up at a conference recently: “isn’t the single GenServer a bottleneck?” No — the CRUD functions run in the caller’s process and delegate straight to the adapter, so reads/writes get full ETS/Mnesia concurrency. The GenServer only handles lifecycle, state, and the TTL sweep.
Docs: hexdocs.pm/active_memory · Repo: github.com/SullysMustyRuby/active_memory
Would love feedback, use cases, or contributions — and if anything in the new features doesn’t behave as documented, please open an issue. Thanks!
Last Post!
thiagomajesk
I kid you not, I was just trying to find this library on the forum yesterday, but I couldn’t remember the name, so I guess thanks for the reminder!? haha ![]()
I’ve been working on some games for the past few years, and I always end up creating custom loaders which end up being some version of this, so this library is going to be super helpful. Congratulations on the project! ![]()
Popular in Announcing
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









