Nebulex: a caching abstraction and cache operations layer for Elixir
In-memory and distributed caching toolkit for Elixir.
At a glance
- What is it?
- Nebulex gives Elixir applications one cache API across local, Redis, and Memcached adapters, with optional decorators, telemetry, and distributed cache patterns. It is a toolkit for teams that want cache behavior separated from application data access, although it does not replace the operational responsibilities of a distributed cache backend.
- Who is it for?
- Nebulex fits Elixir applications that need a stable cache API across multiple backends or want declarative caching around Ecto functions. Teams that require direct Redis or Memcached features not represented by the selected adapter should verify those capabilities first, and applications using the local adapter should account for memory and generation management.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 5 days ago.
- What is it written in?
- Mainly Elixir, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why Nebulex sits between Elixir code and cache backends
Nebulex addresses a specific abstraction problem in Elixir applications. Application code often needs caching behavior while the storage implementation may change between a process-local cache, Redis, Memcached, or another supported adapter. Nebulex lets callers write against the Nebulex API instead of speaking directly to Redis or Memcached. That is useful when cache infrastructure should be selected through configuration or when the same domain logic should continue to work with a different backend.
The intended audience is Elixir developers working with data access, especially applications built with Ecto and supervised OTP services. The README presents Nebulex as an abstraction comparable to Ecto in that it reduces the need to spread backend-specific calls through application code. It does not turn caching into a database replacement, provide query planning, or solve every cache consistency problem. Cache hits and misses remain application-level concerns, and a cache can still return stale data unless the application defines appropriate eviction and expiration behavior.
Nebulex also includes declarative, decorator-based caching. That approach attaches caching patterns to selected functions, which can make cache keys, TTLs, and cache mutations visible beside the functions that use them. The core design is therefore broader than a single cache client. It is an abstraction layer, an operations surface, and a place to express common cache usage patterns.
How the adapter abstraction moves cache calls through Nebulex
The repository README describes the application-facing flow as defining a cache module with `use Nebulex.Cache`, selecting an `adapter:`, adding that cache module to the application's supervision tree, and calling the module's cache operations. The selected adapter determines the underlying storage implementation. For example, the local adapter uses `Nebulex.Adapters.Local`, while the README also identifies Redis, Memcached, and Cachex as examples of technologies that application code can avoid addressing directly through the abstraction.
The local adapter in the README is the Generational Local Cache. Its configuration exposes `gc_interval`, `max_size`, `allocated_memory`, and `gc_memory_check_interval`. The example sets a new generation every 12 hours, permits up to 1 million entries, caps memory at 2,000,000,000 units, and checks size and memory every 10 seconds. The README does not fully explain the internal generation algorithm, so the exact eviction behavior should be checked in the adapter documentation before relying on a particular capacity policy.
At the application level, the initial data flow is short. `put` stores a key and value, while `fetch` retrieves the value as an `:ok` tuple. Decorators add a second layer. A `cacheable` function can derive a key from arguments, apply a TTL, and cache the result of a repository call. A `cache_put` decorator can update or replace an entry after a write, while `cache_evict` removes an entry after deletion. This separation keeps cache policy attached to operations, but it also means key design and write consistency are part of the application's design.
Adding the local adapter and running the first cache operation
The README's first-use path starts by adding Nebulex and an adapter to `mix.exs`. The decorator and telemetry packages are optional, although the README recommends both. For this example, the local adapter is selected. The exact dependency declarations from the README are:
def deps do
[
{:nebulex, "~> 3.0"},
{:nebulex_local, "~> 3.0"},
{:decorator, "~> 1.4"},
{:telemetry, "~> 1.3"}
]
endAfter adding those dependencies, the README instructs the developer to fetch them with `mix deps.get`. That command retrieves the declared dependencies. The README does not provide a separate adapter installation command.
Define the cache module next. The module must use `Nebulex.Cache` and specify the adapter matching the dependency:
defmodule MyApp.Cache do
use Nebulex.Cache,
otp_app: :my_app,
adapter: Nebulex.Adapters.Local
endThe cache module then needs to be a child of the application supervision tree. The README shows the placement, while leaving the rest of an existing supervision tree unspecified:
def start(_type, _args) do
children = [
MyApp.Cache
]
# ... rest of your supervision treeWith the child started, the first operation is a write followed by a read:
iex> MyApp.Cache.put("foo", "bar")
:ok
iex> MyApp.Cache.fetch("foo")
{:ok, "bar"}The README states that `:ok` is returned by the write and `{:ok, "bar"}` by the fetch in this example. It does not show the miss result or error behavior in this short example, so those cases should be checked in the official documentation for the API version being used.
Decorator-based caching for Ecto-backed account operations
The README's larger example shows how Nebulex can place cache policy around Ecto operations. It configures `MyApp.Cache` before defining the cache module, then uses `Nebulex.Caching` in an accounts context. The cache key for a user fetched by ID is `{User, id}`, and the cached entry has a one-hour TTL. A lookup by username uses `{User, username}` and stores a reference to the returned user's ID.
The update example uses `cache_put` after a repository update. Its `match` function receives the update result and returns `{true, value}` for `{:ok, value}`, or `false` for an error. This matters because the decorator can distinguish a successful update from a failed repository operation before deciding what to cache. The delete example uses `cache_evict` keyed by `{User, user.id}`.
A reduced version of the configuration and cache definition is:
config :my_app, MyApp.Cache,
gc_interval: :timer.hours(12),
max_size: 1_000_000,
allocated_memory: 2_000_000_000,
gc_memory_check_interval: :timer.seconds(10)
defmodule MyApp.Cache do
use Nebulex.Cache,
otp_app: :my_app,
adapter: Nebulex.Adapters.Local
endThe operation decorators are concise:
use Nebulex.Caching, cache: MyApp.Cache
@ttl :timer.hours(1)
@decorate cacheable(key: {User, id}, opts: [ttl: @ttl])
def get_user!(id) do
Repo.get!(User, id)
end
@decorate cache_evict(key: {User, user.id})
def delete_user(%User{} = user) do
Repo.delete(user)
endThis pattern is attractive when a domain context has several coordinated cache operations. Its cost is that key shapes and invalidation rules become application code that must remain correct when queries or write flows change. The README does not document a general rollback procedure, transaction-aware cache invalidation, or a universal stale-read policy, so those cases require design work beyond this setup.
Choosing local, Redis, or Memcached implementations
Nebulex's central trade-off is abstraction versus backend-specific access. The README says that developers use the Nebulex API rather than talking directly to Redis, Memcached, or an Elixir cache such as Cachex. That can reduce coupling in application modules and make backend selection an infrastructure decision. It does not mean that every feature of the underlying service is available through the same interface.
A local adapter is appropriate when the cache can live inside the Elixir node and the application can accept node-local memory and process lifecycle boundaries. The documented configuration provides explicit entry and memory limits, which makes capacity planning possible at a basic level. A Redis or Memcached adapter is more relevant when a separate cache service is preferred or when the architecture requires a cache outside the BEAM node. The README names those adapters but does not give their configuration snippets in this README, so the adapters guide is the correct place to verify supported options.
Compared with using a Redis client directly, Nebulex moves common operations behind a common API and adds a place for declarative cache policy. Compared with Cachex, the README positions Nebulex as a broader abstraction that also includes adapter choices and distributed cache topology guidance. The exact behavior of transactions, pipelines, locking, pub/sub, and backend-specific commands is not established by the README. A team choosing a backend should therefore inspect the selected adapter documentation before assuming parity with direct client access.
Maintenance, licensing, and the cost of adopting Nebulex
The repository is not archived, and the last push was on 2026-10-12. The project has recent release entries in the repository metadata, including v3.0.4 dated 2026-05-03, v3.0.3 dated 2026-03-27, and v3.0.2 dated 2026-03-07. The README also points to an “Upgrading to v3.0” migration guide. That indicates a versioned project with an explicit migration path, although the README does not establish the compatibility policy for older releases.
The maintenance cost for an adopting application comes from several places. Application code must follow the Nebulex API rather than a particular cache client's API. Cache modules must be supervised. Key conventions must be kept stable across functions, because changing a key shape can leave old entries inaccessible until their TTL or eviction policy removes them. Distributed deployments also require attention to the topology and to operations after writes, which the README covers through links to cache topology and declarative caching guidance.
Nebulex is released under the MIT License. That is a permissive license, but license implications for a particular product, deployment, or distribution should be evaluated from the project's license text and applicable policies. The README does not provide legal guidance or claim that the license removes all obligations. Upgrade planning should begin with the v3.0 migration guide and the chosen adapter's release notes.
The repository includes `test/`, `benchmarks/`, `guides/`, and CI-related files. The README documents `mix test` for running only tests and `mix precommit` for running the full CI alias, which includes tests, coverage, Credo, Dialyzer, and other checks. Those commands describe repository workflows, not a guarantee that every adapter or deployment configuration is covered.
Editorial conclusion
Nebulex fits Elixir applications that need a stable cache API across multiple backends or want declarative caching around Ecto functions. Teams that require direct Redis or Memcached features not represented by the selected adapter should verify those capabilities first, and applications using the local adapter should account for memory and generation management. The first checks are the adapter choice, cache supervision, eviction behavior, and the v3.0 migration documentation when upgrading.
Frequently asked questions
How do I install Nebulex with the local cache adapter in an Elixir project?
Add `{:nebulex, "~> 3.0"}`, `{:nebulex_local, "~> 3.0"}`, and the optional `:decorator` and `:telemetry` dependencies to `mix.exs`, then run `mix deps.get`. Define a module with `adapter: Nebulex.Adapters.Local` and add it to the supervision tree.
Does Nebulex replace Redis or Memcached?
Nebulex abstracts access to supported cache backends through a common Elixir API. The README names Redis and Memcached as backends that application code can avoid addressing directly, but the selected adapter determines which backend features are available.
How does declarative caching work with Ecto in Nebulex?
The `Nebulex.Caching` module supports decorators such as `cacheable`, `cache_put`, and `cache_evict`. The README shows these decorators attached to functions that call `Repo.get!`, `Repo.update`, or `Repo.delete`, with cache keys, TTLs, and write matching defined beside the functions.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/elixir-nebulex-nebulex)Was this useful?