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:latestOr explicitly:
-e NOTIFY_STORE_DRIVER=memoryLibrary 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.RWMutexguards 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 -vAll 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)) }}