Chimeway

Chimeway is a local-first, explainable, durable notification library for Elixir. It runs inside your application and your database — there is no external notification SaaS to trust or route your recipient data through. Every notification decision is traceable — teams can reliably answer why a notification sent, failed, or was suppressed.

Hex.pmCI

When to use

Reach for Chimeway when you want embedded, local-first notifications with an auditable trace:

Non-goals

Chimeway is intentionally not:

Host-owned boundaries

Your application owns the surfaces at the trust boundary; Chimeway never assumes them:

Optional surfaces

Two sibling packages extend Chimeway but are optional and ship in this repository as an in-repo preview/path package — each is not published on Hex yet:

Add them via a path: dependency from this repo when you want to preview them; they are not current Hex installs.

Installation

Add chimeway to your mix.exs dependencies:

def deps do
[
{:chimeway, "~> 1.1"}
]
end

Then run:

mix deps.get
mix chimeway.gen.migrations
mix ecto.migrate

Choose the runtime storage prefix before starting Chimeway. New installs should use the new isolated Chimeway schema:

config :chimeway, prefix: "chimeway"

Use prefix: false only for an existing public-schema legacy install whose Chimeway tables already live in public:

config :chimeway, prefix: false

That legacy mode keeps using the existing unprefixed tables and does not move data.

Quick Start

Follow the Golden Path guide for install, notifier setup, and your first explainable trace.

Chimeway.trigger(MyApp.Notifiers.WelcomeUser, %{user_id: "u1", name: "Ada"},
idempotency_key: "welcome-u1",
tenant_id: "default"
)

Trigger to explainable trace

The canonical path is: define a notifier with a stable key, trigger it, then explain the delivery. Every snippet below uses the real public API.

1. Define a notifier — the stable key is the notification_key/0 return value (with version/0):

defmodule MyApp.Notifiers.WelcomeUser do
use Chimeway.Notifier
@impl true
def notification_key, do: "welcome_user"
@impl true
def version, do: 1
end

2. Configure the runtime storage prefix:

config :chimeway, prefix: "chimeway"

3. Trigger — both tenant_id and idempotency_key are always required:

{:ok, result} =
Chimeway.trigger(MyApp.Notifiers.WelcomeUser, %{user_id: "user_12345"},
idempotency_key: "signup_user_12345",
tenant_id: "default"
)

4. Explain the delivery — look up why it sent, failed, or was suppressed:

[delivery_id | _] = result.trace.delivery_ids
{:ok, explanation} = Chimeway.Traces.explain_delivery(delivery_id)

Chimeway.Traces.explain_delivery/1 returns the delivery status, any suppression reason, and the full timeline — the answer to "why did (or didn't) this notification go out?"

Documentation

License

MIT — see LICENSE.md.