View Source Pow.Store.Backend.MnesiaCache (Pow v1.0.38)

GenServer based key value Mnesia cache store with auto expiration.

When the MnesiaCache starts, it will initialize invalidators for all stored keys using the expire value. If the expire datetime is past, it will call the invalidator immediately.

Mnesia will create a Mnesia.Node directory in the current working directory to write files to. This can be changed by setting the -mnesia dir config:

config :mnesia, dir: '/path/to/dir'

The directory path should be accessible, otherwise MnesiaCache will crash on startup.

:mnesia should be added to :extra_applications in mix.exs for it to be included in releases.


The MnesiaCache is built to handle multi-node setup.

If you initialize with extra_db_nodes: Node.list(), it will automatically connect to the cluster. You can also use MFA: extra_db_nodes: {Node, :list, []}. This is useful for when nodes are dynamically connected before MnesiaCache startup in the supervision tree.

If there is no other nodes available, the data persisted to disk will be loaded, but if a cluster is running, the data in the existing cluster nodes will be loaded instead of the local data. This could potentially cause data loss, but is an accepted risk as all data stored by Pow should be ephemeral.

When a cache key expires, the expiration will be verified before deletion to ensure that it hasn't been updated by another node. When a key is updated on a node, the node will ping all other nodes to refresh their invalidators so the new TTL is used.

All nodes spun up will by default persist to disk. If you start up multiple nodes from the same physical directory you have to make sure that each node has a unique directory path configured. This can be done using different config files, or by using a system environment variable:

config :mnesia, dir: to_charlist(System.get_env("MNESIA_DIR"))

You can use Pow.Store.Backend.MnesiaCache.Unsplit to automatically recover from network split issues. All partitioned nodes will have their table flushed and reloaded from the oldest node in the cluster.


To start the GenServer, add it to your application start/2 function:

defmodule MyApp.Application do
  use Application

  def start(_type, _args) do
    children = [
      # # Or in a distributed system:
      # {Pow.Store.Backend.MnesiaCache, extra_db_nodes: {Node, :list, []}},
      # Pow.Store.Backend.MnesiaCache.Unsplit # Recover from netsplit

    opts = [strategy: :one_for_one, name: MyAppWeb.Supervisor]
    Supervisor.start_link(children, opts)

  # ...

Update configuration with cache_store_backend: Pow.Store.Backend.MnesiaCache.

Initialization options

  • :extra_db_nodes - list of nodes or MFA returning a list of nodes in cluster to connect to.

  • :table_opts - options to add to table definition. This value defaults to [disc_copies: [node()]].

  • :timeout - timeout value in milliseconds for how long to wait until the cache table has initiated. Defaults to 15 seconds.

Configuration options

  • :ttl - integer value in milliseconds for ttl of records (required).

  • :namespace - string value to use for namespacing keys, defaults to "cache".

  • :writes - set to :async to do asynchronous writes. Defaults to :sync.



Returns a specification to start this module under a supervisor.


Returns a specification to start this module under a supervisor.

See Supervisor.