Skip to content

Key-Value Store

Fast key-value storage with TTL support. Ideal for caching, sessions, and temporary state.

For store configuration, see Store.

local store = require("store")

Get a store resource by registry ID:

local cache, err = store.get("app:cache")
if err then
return nil, err
end
cache:set("user:123", {name = "Alice"}, 3600)
local user = cache:get("user:123")
cache:release()
ParameterTypeDescription
idstringStore resource ID

Returns: Store, error

Store a value with optional TTL:

local cache = store.get("app:cache")
-- Simple set
cache:set("user:123:name", "Alice")
-- Set with TTL (expires in 300 seconds)
cache:set("session:abc", {user_id = 123, role = "admin"}, 300)
ParameterTypeDescription
keystringKey
valueanyValue (tables, strings, numbers, booleans)
ttlnumberTTL in seconds (optional, 0 = no expiry)

Returns: boolean, error

Get a value by key:

local user = cache:get("user:123")
if not user then
-- Key not found or expired
end
ParameterTypeDescription
keystringKey to retrieve

Returns: any, error

Returns nil and an errors.NOT_FOUND error if the key doesn’t exist or has expired.

Check if a key exists without retrieving:

if cache:has("lock:" .. resource_id) then
return nil, errors.new("CONFLICT", "Resource is locked")
end
ParameterTypeDescription
keystringKey to check

Returns: boolean, error

Remove a key from the store:

cache:delete("session:" .. session_id)
ParameterTypeDescription
keystringKey to delete

Returns: boolean, error

Returns true if deleted, false if key didn’t exist.

entry returns the value together with its version — an opaque string used for optimistic concurrency:

local e, err = cache:entry("user:123")
if e then
print(e.key, e.value, e.version)
end
ParameterTypeDescription
keystringKey to read

Returns: Entry, error{key: string, value: any, version: string}

List entries in deterministic key order, with paging:

local page, err = cache:list({ prefix = "session:", limit = 100 })
for _, e in ipairs(page.items) do
print(e.key, e.value)
end
-- next page
if page.has_more then
page = cache:list({ prefix = "session:", after = page.cursor })
end
OptionTypeDescription
prefixstringOnly keys with this prefix
afterstringContinue after this cursor (from a previous page)
limitintegerMax items per page

Returns: Page, error{items: Entry[], cursor: string, has_more: boolean}

put writes a value and returns its new Entry. Options enable optimistic concurrency:

-- create only if the key does not exist
local e, err = cache:put("lock:job-1", owner, { only_if_absent = true })
if err and err:kind() == errors.ALREADY_EXISTS then
-- someone else holds it
end
-- compare-and-set: write only if the version still matches
local cur = cache:entry("config")
local e2, err2 = cache:put("config", new_value, { if_version = cur.version })
if err2 and err2:kind() == errors.CONFLICT then
-- a concurrent writer changed it; re-read and retry
end
OptionTypeDescription
ttlnumberTTL in seconds
only_if_absentbooleanWrite only if the key does not exist
if_versionstringWrite only if the current version matches

only_if_absent and if_version are mutually exclusive.

Returns: Entry, error

Conditional writes require a store whose info().conditional_put is true (the memory and store.kv.raft stores). On store.kv.crdt and store.sql they return an errors.INVALID error — use store.kv.raft when you need conditional writes.

info reports the backend and what it supports, so code can adapt to whichever store is bound:

local info = cache:info()
-- info.backend -> one of store.backend.* (e.g. "kv.raft")
-- info.consistency -> one of store.consistency.* (e.g. "linearizable")
-- info.durable / info.list / info.versioned / info.conditional_put / info.ttl (booleans)

Returns: Info, error{id, backend, consistency, durable, list, versioned, conditional_put, ttl}

ConstantValues
store.backendMEMORY, SQL, KV_RAFT, KV_CRDT, UNKNOWN
store.consistencyLINEARIZABLE, EVENTUAL, LOCAL, UNKNOWN
if cache:info().consistency == store.consistency.LINEARIZABLE then
-- safe to use compare-and-set
end
MethodReturnsDescription
get(key)any, errorRetrieve value by key
entry(key)Entry, errorRetrieve value with version metadata
set(key, value, ttl?)boolean, errorStore value with optional TTL
put(key, value, opts?)Entry, errorConditional/versioned write, returns the new entry
list(opts?)Page, errorPaged listing in key order
has(key)boolean, errorCheck if key exists
delete(key)boolean, errorRemove key
info()Info, errorBackend, consistency, and capability flags
release()booleanRelease store back to pool

Store operations are subject to security policy evaluation.

ActionResourceAttributesDescription
store.getStore ID-Acquire a store resource
store.infoStore ID-Inspect store capabilities
store.key.getStore IDkeyRead a key value (also entry)
store.key.setStore IDkeyWrite a key value (also put)
store.key.deleteStore IDkeyDelete a key
store.key.hasStore IDkeyCheck key existence
store.key.listStore IDprefixList entries

store.get() and all methods on the store handle (get, entry, set, put, list, has, delete, info) return structured errors (use err:kind()).

ConditionKindRetryable
Empty resource IDerrors.INVALIDno
Resource not founderrors.NOT_FOUNDno
Store releasederrors.INVALIDno
Permission deniederrors.PERMISSION_DENIEDno
only_if_absent and key existserrors.ALREADY_EXISTSno
if_version mismatcherrors.CONFLICTyes
Conditional write on a store without supporterrors.INVALIDno

See Error Handling for working with errors.