High-throughput, in-memory cache backed by ETS.
Works in both local (single-node) and distributed (cluster) modes.
The mode is selected at startup via the :cluster option and is
transparent to callers — the same API covers both.
Setup
# Local (single-node, default)
SuperCache.start!(key_pos: 0, partition_pos: 0)
# Distributed cluster
SuperCache.start!(
key_pos: 0,
partition_pos: 0,
cluster: :distributed,
replication_factor: 2,
replication_mode: :async,
num_partition: 16
)
# Enable debug logging
# in config.exs:
# config :super_cache, debug_log: trueOptions
| Option | Type | Default | Description |
|---|---|---|---|
:key_pos | integer | 0 | Tuple index used as the ETS key |
:partition_pos | integer | 0 | Tuple index used to select partition |
:cluster | atom | :local | :local or :distributed |
:num_partition | integer | scheduler count | Number of ETS partitions |
:table_type | atom | :set | ETS table type |
Read modes (meaningful in distributed mode)
| Mode | Consistency | Latency |
|---|---|---|
:local | Eventual (default) | Zero extra latency |
:primary | Strong per key | +1 RTT if non-primary |
:quorum | Majority vote | +1 RTT (parallel) |
Replication modes (distributed mode only)
| Mode | Guarantee | Extra latency |
|---|---|---|
:async | Eventual (default) | None |
:sync | At-least-once | +1 RTT per write |
:strong | Three-phase commit | +3 RTTs per write |
Basic usage
SuperCache.put!({:user, 1, "Alice"})
SuperCache.get!({:user, 1, nil})
# => [{:user, 1, "Alice"}]
# Read modes (distributed)
SuperCache.get!({:user, 1, nil}, read_mode: :primary)
SuperCache.get!({:user, 1, nil}, read_mode: :quorum)
SuperCache.delete!({:user, 1, nil})
SuperCache.delete_all()Error handling
!-suffix functions raise on error. Non-bang variants return
{:error, exception} instead and never raise.
Summary
Functions
Return an aggregated cluster-wide statistics map.
Non-raising variant of delete!/1.
Delete the record matching the key in data.
Delete all records from every partition.
Non-raising variant of delete_by_key_partition!/2.
Delete by explicit key and partition_data.
Non-raising variant of delete_by_match!/2.
Delete from all partitions. Equivalent to delete_by_match!(:_, pattern).
Delete records matching pattern in partition_data (or all partitions for :_).
Delete a record directly from a specific partition table.
Delete a record directly from a partition by its integer index.
Non-raising variant of delete_same_key_partition!/1.
Equivalent to delete_by_key_partition!(key, key) — for tables where key_pos == partition_pos.
Returns true when SuperCache is running in distributed mode.
Retrieve records. Returns [tuple] | {:error, exception} instead of raising.
Retrieve all records whose key matches the key element of data.
Non-raising variant of get_by_key_partition!/3.
Retrieve records by explicit key and partition_data.
Non-raising variant of get_by_match!/2.
Scan all partitions. Equivalent to get_by_match!(:_, pattern, []).
Retrieve records matching an ETS match pattern (binding lists).
Non-raising variant of get_by_match_object!/2.
Scan all partitions. Equivalent to get_by_match_object!(:_, pattern, []).
Retrieve full records matching an ETS match-object pattern.
Retrieve records directly from a specific partition table.
Retrieve records directly from a partition by its integer index.
Non-raising variant of get_same_key_partition!/2.
Equivalent to get_by_key_partition!(key, key, opts) — for tables where key_pos == partition_pos.
Enqueue a tuple for a buffered (lazy) write.
Store a tuple. Returns true | {:error, exception} instead of raising.
Store a tuple in the cache.
Store multiple tuples in a single batch operation.
Store a tuple directly into a specific partition table.
Store a tuple directly into a partition by its integer index.
Non-raising variant of scan!/3.
Equivalent to scan!(:_, fun, acc).
Fold over every record in a partition (or all when :_).
Start SuperCache. Returns :ok | {:error, exception} instead of raising.
Start SuperCache with opts. Returns :ok | {:error, exception} instead of raising.
Start SuperCache with default options (local, key_pos: 0, partition_pos: 0).
Start SuperCache with the given keyword options. Raises on invalid config.
Returns true when SuperCache is running and ready.
Return local ETS record counts per partition plus :total.
Stop SuperCache and free all ETS memory.
Functions
@spec cluster_stats() :: map()
Return an aggregated cluster-wide statistics map.
In local mode wraps stats/0 in the same map format for a uniform interface.
In distributed mode gathers per-node counts via :erpc.
@spec delete(tuple()) :: :ok | {:error, Exception.t()}
Non-raising variant of delete!/1.
@spec delete!(tuple()) :: :ok
Delete the record matching the key in data.
Routes to the primary in distributed mode.
@spec delete_all() :: :ok
Delete all records from every partition.
In distributed mode, issues one routed delete per partition to its primary.
@spec delete_by_key_partition(any(), any()) :: :ok | {:error, Exception.t()}
Non-raising variant of delete_by_key_partition!/2.
Delete by explicit key and partition_data.
@spec delete_by_match(any(), tuple()) :: :ok | {:error, Exception.t()}
Non-raising variant of delete_by_match!/2.
@spec delete_by_match!(tuple()) :: :ok
Delete from all partitions. Equivalent to delete_by_match!(:_, pattern).
Delete records matching pattern in partition_data (or all partitions for :_).
Delete a record directly from a specific partition table.
Bypasses all routing and partition resolution.
Examples
partition = SuperCache.Partition.get_partition(:my_key)
SuperCache.delete_partition!(:user, partition)
# => :ok
@spec delete_partition_by_idx!(any(), non_neg_integer()) :: :ok
Delete a record directly from a partition by its integer index.
This is the fastest delete path — bypasses routing and partition resolution.
Examples
idx = SuperCache.Partition.get_partition_order(:my_key)
SuperCache.delete_partition_by_idx!(:user, idx)
# => :ok
@spec delete_same_key_partition(any()) :: :ok | {:error, Exception.t()}
Non-raising variant of delete_same_key_partition!/1.
@spec delete_same_key_partition!(any()) :: :ok
Equivalent to delete_by_key_partition!(key, key) — for tables where key_pos == partition_pos.
@spec distributed?() :: boolean()
Returns true when SuperCache is running in distributed mode.
Delegates to Config.distributed?/0 for zero-cost persistent_term reads.
@spec get( tuple(), keyword() ) :: [tuple()] | {:error, Exception.t()}
Retrieve records. Returns [tuple] | {:error, exception} instead of raising.
Retrieve all records whose key matches the key element of data.
Options
:read_mode—:local(default),:primary, or:quorum.
Examples
SuperCache.get!({:user, 1, nil})
SuperCache.get!({:user, 1, nil}, read_mode: :primary)
SuperCache.get!({:user, 1, nil}, read_mode: :quorum)
@spec get_by_key_partition(any(), any(), keyword()) :: [tuple()] | {:error, Exception.t()}
Non-raising variant of get_by_key_partition!/3.
Retrieve records by explicit key and partition_data.
Options
:read_mode—:local(default),:primary, or:quorum.
@spec get_by_match(any(), tuple(), keyword()) :: [[any()]] | {:error, Exception.t()}
Non-raising variant of get_by_match!/2.
Scan all partitions. Equivalent to get_by_match!(:_, pattern, []).
Retrieve records matching an ETS match pattern (binding lists).
Pass :_ as partition_data to scan all partitions.
Options
:read_mode—:local(default),:primary, or:quorum.
@spec get_by_match_object(any(), tuple(), keyword()) :: [tuple()] | {:error, Exception.t()}
Non-raising variant of get_by_match_object!/2.
Scan all partitions. Equivalent to get_by_match_object!(:_, pattern, []).
Retrieve full records matching an ETS match-object pattern.
Pass :_ as partition_data to scan all partitions.
Options
:read_mode—:local(default),:primary, or:quorum.
Retrieve records directly from a specific partition table.
Bypasses all routing and partition resolution. The key is looked up
directly in the given partition table.
Examples
partition = SuperCache.Partition.get_partition(:my_key)
SuperCache.get_partition!(:user, partition)
# => [{:user, 1, "Alice"}]
@spec get_partition_by_idx!(any(), non_neg_integer()) :: [tuple()]
Retrieve records directly from a partition by its integer index.
This is the fastest read path — bypasses routing, partition resolution, and partition table name lookup.
Examples
idx = SuperCache.Partition.get_partition_order(:my_key)
SuperCache.get_partition_by_idx!(:user, idx)
# => [{:user, 1, "Alice"}]
@spec get_same_key_partition( any(), keyword() ) :: [tuple()] | {:error, Exception.t()}
Non-raising variant of get_same_key_partition!/2.
Equivalent to get_by_key_partition!(key, key, opts) — for tables where key_pos == partition_pos.
@spec lazy_put(tuple()) :: :ok
Enqueue a tuple for a buffered (lazy) write.
Falls back to put!/1 with a warning when :strong replication is active.
@spec put(tuple()) :: true | {:error, Exception.t()}
Store a tuple. Returns true | {:error, exception} instead of raising.
@spec put!(tuple()) :: true
Store a tuple in the cache.
In distributed mode, routes the write to the partition's primary node and
replicates according to :replication_mode. Raises on error.
@spec put_batch!([tuple()]) :: :ok
Store multiple tuples in a single batch operation.
In distributed mode, groups data by partition and sends each group
in a single :erpc call, dramatically reducing network overhead.
Example
SuperCache.put_batch!([
{:user, 1, "Alice"},
{:user, 2, "Bob"},
{:session, "tok1", :active}
])
Store a tuple directly into a specific partition table.
Bypasses all routing and partition resolution. Use when you already know
the target partition table atom (e.g., from a previous get_partition/1
call or from Partition.get_all_partition/0).
Examples
partition = SuperCache.Partition.get_partition(:my_key)
SuperCache.put_partition!({:user, 1, "Alice"}, partition)
@spec put_partition_by_idx!(tuple(), non_neg_integer()) :: true
Store a tuple directly into a partition by its integer index.
This is the fastest write path — bypasses routing, partition resolution,
and even the partition table name lookup. The index is used directly to
fetch the cached partition table atom from persistent_term.
Examples
# Get partition index once
idx = SuperCache.Partition.get_partition_order(:my_key)
# Use it for fast repeated access
SuperCache.put_partition_by_idx!({:user, 1, "Alice"}, idx)
Non-raising variant of scan!/3.
Equivalent to scan!(:_, fun, acc).
Fold over every record in a partition (or all when :_).
Always reads from the local ETS table regardless of replication mode.
@spec start() :: :ok | {:error, Exception.t()}
Start SuperCache. Returns :ok | {:error, exception} instead of raising.
@spec start(keyword()) :: :ok | {:error, Exception.t()}
Start SuperCache with opts. Returns :ok | {:error, exception} instead of raising.
@spec start!() :: :ok
Start SuperCache with default options (local, key_pos: 0, partition_pos: 0).
@spec start!(keyword()) :: :ok
Start SuperCache with the given keyword options. Raises on invalid config.
@spec started?() :: boolean()
Returns true when SuperCache is running and ready.
@spec stats() :: keyword()
Return local ETS record counts per partition plus :total.
@spec stop() :: :ok
Stop SuperCache and free all ETS memory.