Last updated 2026-05-28

Memory store

The memory driver is the in-process reference implementation. All state lives in Go maps protected by a mutex; restart loses everything. It is the differential reference for the conformance suite — every other driver is verified against memory's exact behaviour.

When you'd use this

  • Tests & CI — your unit tests that exercise notify's contract via a fake store.
  • Local development / demos — no DB to provision; restart the container to clear state.
  • Ephemeral environments — preview deployments that don't need durability.

Selecting it

It is the default. No env vars required.

docker run --rm \
-p 8080:8080 -p 8081:8081 -p 9090:9090 \
-e NOTIFY_AUTH_DEV_MODE=true \
ghcr.io/elloloop/notify:latest

Or explicitly:

-e NOTIFY_STORE_DRIVER=memory

Library wiring

import (
"github.com/elloloop/notify"
"github.com/elloloop/notify/store/memory"
)
store := memory.New()
notifier := notify.NewNotifier(store, providers)

Characteristics

  • Thread-safe — a single sync.RWMutex guards two maps.
  • Idempotent on (tenant, user, notification_id) — repeat creates return the existing id with created=false.
  • O(n) page scans — adequate for the test workloads; not optimised for very large inboxes (which is why Postgres exists).
  • No background work — no timers, no goroutines beyond what the caller drives.

Running the conformance suite locally

go test ./store/memory/... -race -count=1 -v

All 24 leaf subtests across the six categories pass. memory is the fastest of the three (no testcontainer warm-up, no EntDB SDK handshake) and is the gate that catches a botched conformance refactor before the slower drivers run.

Using it as the reference in your own tests

If you are writing tests that exercise notify's behaviour from your consumer's POV — without spinning up Postgres or EntDB — wire memory directly:

func TestMyService_SendsNotification(t *testing.T) {
store := memory.New()
providers := notify.NewProviderRegistry()
providers.Register(&fakeEmailProvider{})
notifier := notify.NewNotifier(store, providers, notify.WithClock(func() time.Time {
return time.Unix(1748390400, 0)
}))
myService := NewMyService(notifier)
myService.DoTheThing(ctx, "user-alice")
items, _, _, _ := store.QueryUserNotifications(ctx, notify.Query{
TenantID: "acme", UserID: "user-alice",
})
if len(items) != 1 {
t.Fatalf("expected one stored row, got %d", len(items))
}
}

Related