MemoryStore gives you a typed, namespaced key-value store attached directly to the request context so you never have to thread raw store handles through your handler code.
How it works
MemoryStore wraps any StateStore backend and scopes every key to a namespace, so two sessions never collide. The withMemory middleware creates a fresh MemoryStore for each incoming request and writes it to ctx.state.memory. Your handler reads and writes memory without knowing anything about the underlying store.
The default backend is SQLite (via
SqliteStateStore). You can swap in any implementation of the StateStore interface — see Custom backends below.Quick start
Register the withMemory middleware
Apply
withMemory to any router or route that needs per-session memory.Namespacing
EachMemoryStore instance is scoped to a namespace so that different sessions or users never read each other’s data. By default withMemory derives the namespace from the x-session-id request header, falling back to 'default' when the header is absent.
Pass a namespace function to compute a namespace from any request property:
MemoryStore API
memory.get<T>(key)
Returns the stored value cast to T, or undefined if the key does not exist.
memory.set(key, value)
Stores any JSON-serializable value under key. Overwrites any existing value.
memory.append<T>(key, item)
Pushes item onto the end of the array stored at key. If the key does not exist, creates a new single-element array. Returns the new array length.
memory.delete(key)
Removes the key from the namespace. No-op if the key does not exist.
memory.keys()
Returns all keys registered under the current namespace. Useful for inspecting or clearing state.
Full example: remembering a user’s name
The following route greets a returning user by name and saves new users for future requests.Custom backends
MemoryStore works with any object that satisfies the StateStore interface. You can provide Redis, Postgres, or any other persistence layer:
StateStore interface requires four methods:
| Method | Signature | Description |
|---|---|---|
get | get<T>(key): Promise<T | undefined> | Retrieve a value by key |
set | set(key, value): Promise<void> | Persist any JSON-serializable value |
delete | delete(key): Promise<void> | Remove a key |
list | list(prefix?): Promise<string[]> | List keys, optionally filtered by prefix |
For development and tests, use the zero-dependency
MemoryStateStore from anvil/store. It stores values in-process and requires no native dependencies.