Key-Value Store

The store module provides key-value storage with optional TTLs. It can hold cached data, sessions, and other temporary state.

This page is an API reference. Its snippets assume a configured store, the permissions listed below, and application-provided values such as owner or new_value. Snippets after acquisition use an existing live cache handle and are not standalone functions.

For store configuration, see Store.

Loading

local store = require("store")

Acquiring a Store

Acquire a store resource by registry ID:

local cache, err = store.get("app:cache")
if err then
    return nil, err
end

local _, set_err = cache:set("user:123", {name = "Alice"}, 3600)
if set_err then
    cache:release()
    return nil, set_err
end

local user, get_err = cache:get("user:123")

cache:release()
if get_err then return nil, get_err end
return user
Parameter Type Description
id string Store resource ID

Returns: Store, error

Storing Values

Store a value with an optional TTL:

-- Simple set
local _, err = cache:set("user:123:name", "Alice")
if err then return nil, err end

-- Set with TTL (expires in 300 seconds)
local ok, ttl_err = cache:set("session:abc", {user_id = 123, role = "admin"}, 300)
if ttl_err then return nil, ttl_err end
return ok
Parameter Type Description
key string Key
value any Value (tables, strings, numbers, booleans)
ttl number TTL in seconds (optional, 0 = no expiry)

Returns: boolean, error

Retrieving Values

Retrieve a value by key:

local errors = require("errors")

local user, err = cache:get("user:123")
if err then
    if err:kind() == errors.NOT_FOUND then
        return nil -- key missing or expired
    end
    return nil, err
end
return user
Parameter Type Description
key string Key to retrieve

Returns: any, error

The method returns nil and an errors.NOT_FOUND error when the key does not exist or has expired.

Checking Existence

Check whether a key exists without retrieving its value:

if cache:has("lock:" .. resource_id) then
    return nil, errors.new({ kind = errors.CONFLICT, message = "Resource is locked" })
end
Parameter Type Description
key string Key to check

Returns: boolean, error

Deleting Keys

Remove a key from the store:

local deleted, err = cache:delete("session:" .. session_id)
if err then return nil, err end
return deleted
Parameter Type Description
key string Key to delete

Returns: boolean, error

The method returns true when it deletes the key and false when the key does not exist.

Reading Entry Metadata

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

local e, err = cache:entry("user:123")
if err then return nil, err end
if e then
    print(e.key, e.value, e.version)
end
Parameter Type Description
key string Key to read

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

Listing Keys

List entries in deterministic key order with pagination:

local page, err = cache:list({ prefix = "session:", limit = 100 })
if err then return nil, err end
for _, e in ipairs(page.items) do
    print(e.key, e.value)
end

-- next page
if page.has_more then
    local next_page, next_err = cache:list({ prefix = "session:", after = page.cursor })
    if next_err then return nil, next_err end
    page = next_page
end
Option Type Description
prefix string Only keys with this prefix
after string Continue after this cursor (from a previous page)
limit integer Max items per page

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

Conditional Writes

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

local errors = require("errors")

-- 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
elseif err then
    return nil, err
end

-- compare-and-set: write only if the version still matches
local cur, read_err = cache:entry("config")
if read_err then return nil, read_err end
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
elseif err2 then
    return nil, err2
end
Option Type Description
ttl number TTL in seconds
only_if_absent boolean Write only if the key does not exist
if_version string Write 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.

Store Capabilities

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

local info, err = cache:info()
if err then return nil, err end
-- 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}

Constants

Constant Values
store.backend MEMORY, SQL, KV_RAFT, KV_CRDT, UNKNOWN
store.consistency LINEARIZABLE, EVENTUAL, LOCAL, UNKNOWN
local info, err = cache:info()
if err then return nil, err end
if info.consistency == store.consistency.LINEARIZABLE then
    -- safe to use compare-and-set
end

Store Methods

Method Returns Description
get(key) any, error Retrieve value by key
entry(key) Entry, error Retrieve value with version metadata
set(key, value, ttl?) boolean, error Store value with optional TTL
put(key, value, opts?) Entry, error Conditional/versioned write, returns the new entry
list(opts?) Page, error Paged listing in key order
has(key) boolean, error Check if key exists
delete(key) boolean, error Remove key
info() Info, error Backend, consistency, and capability flags
release() boolean Release store back to pool

Permissions

Security policy evaluation applies to store operations.

Action Resource Attributes Description
store.get Store ID - Acquire a store resource
store.info Store ID - Inspect store capabilities
store.key.get Store ID key Read a key value (also entry)
store.key.set Store ID key Write a key value (also put)
store.key.delete Store ID key Delete a key
store.key.has Store ID key Check key existence
store.key.list Store ID prefix List entries

Permission denials from store.get, get, set, delete, and has raise a Lua error. The info, entry, list, and put methods instead return an errors.PERMISSION_DENIED error. Grant the required actions before calling code that cannot tolerate a raised denial.

Errors

store.get() and all methods on the store handle (get, entry, set, put, list, has, delete, info) return structured errors (use err:kind()), except that a permission denial in store.get, get, set, has and delete raises a Lua error instead.

Condition Kind Retryable
Empty resource ID errors.INVALID no
Resource not found errors.INTERNAL no
Store released errors.INVALID no
Permission denied (entry, put, list, info) errors.PERMISSION_DENIED no
only_if_absent and key exists errors.ALREADY_EXISTS no
if_version mismatch errors.CONFLICT yes
Conditional write on a store without support errors.INVALID no

See Error Handling for working with errors.