Skip to content

Store (Key-Value)

Key-value stores with TTL support: in-memory, SQL-backed, and cluster-replicated (Raft and CRDT).

KindDescription
store.memoryIn-memory store with automatic cleanup
store.sqlSQL-backed store with persistence
store.kv.raftCluster-replicated, strongly-consistent KV on the shared Raft
store.kv.crdtCluster-replicated, eventually-consistent KV over gossip (CRDT)
- name: sessions
kind: store.memory
max_size: 10000
cleanup_interval: "5m"
lifecycle:
auto_start: true
FieldTypeDefaultDescription
max_sizeint10000Maximum entries; 0 is replaced with the default (10000)
cleanup_intervalduration5mExpired entry cleanup interval

When max_size is reached, new entries are rejected. Data is lost on restart.

- name: cache
kind: store.sql
database: app:postgres
table_name: kv_store
cleanup_interval: "10m"
lifecycle:
auto_start: true
FieldTypeDefaultDescription
databasereferencerequiredDatabase entry reference
table_namestringrequiredTable name for storage
id_column_namestringkeyColumn for keys
payload_column_namestringvalueColumn for values
expire_column_namestringexpires_atColumn for expiration
cleanup_intervalduration0Expired entry cleanup interval

Column names are validated against SQL injection. Create the table before use:

CREATE TABLE kv_store (
key VARCHAR(255) PRIMARY KEY,
value BYTEA NOT NULL,
expires_at BIGINT
);
CREATE INDEX idx_expires_at ON kv_store(expires_at) WHERE expires_at IS NOT NULL;

store.kv.raft and store.kv.crdt replicate key-value data across cluster nodes. Both require clustering to be enabled and reuse the same Store Module Lua API. Each entry is a namespaced view into one node-wide engine; namespace isolates this entry’s keys and must match ^[a-z][a-z0-9._-]*$ (it may not start with _).

- name: deployments
kind: store.kv.raft
namespace: deploy
FieldTypeRequiredDescription
namespacestringYesKey namespace in the shared engine

Writes are proposed through the shared Raft (followers forward to the leader); reads are linearizable. Conditional writes (put with only_if_absent/if_version) are supported. Raft state is fs-durable by default under cluster.raft.data_dir (default ~/.wippy/store); see Configuration.

- name: sessions
kind: store.kv.crdt
namespace: sess
durable: false
FieldTypeRequiredDefaultDescription
namespacestringYes-Key namespace
durableboolNofalsePersist fs snapshots so the namespace survives a full-cluster restart

Writes mutate local state and disseminate over gossip; conflicting concurrent writes converge last-writer-wins. Reads are local. Conditional writes are not supported. With durable: false the store is in-memory and reconstructs from peers; with durable: true it snapshots to <data_dir>/_sys/kvcrdt.

data_dir is node-level (cluster.raft.data_dir), not per-entry. The shared Raft state and durable CRDT snapshots live under <data_dir>/_sys/.

Both stores support time-to-live. Expired entries persist briefly until cleanup runs at cleanup_interval. Set to 0 to disable automatic cleanup.

See Store Module for operations: get, set, has, delete, plus put, entry, list, and info for versioned and conditional access.