3. KV Operations
All KV operations target a specific (store_id, group_id).
CLI:
# Put
crowdb-cli kv put --store-id 3 --group-id 3 --key user:1 --value alice
# Get
crowdb-cli kv get --store-id 3 --group-id 3 --key user:1
# Delete
crowdb-cli kv delete --store-id 3 --group-id 3 --key user:1
# Prefix scan (list mode — fast, latest values, S3-list semantics)
crowdb-cli kv scan --store-id 3 --group-id 3 --prefix user: --limit 100
curl:
curl -X POST "http://$IP:$PORT/api/stores/3/groups/3/kv/put" \
-H 'Content-Type: application/json' \
-d '{"key":"user:1","value":"alice"}'
curl "http://$IP:$PORT/api/stores/3/groups/3/kv/get?key=user:1"
curl -X POST "http://$IP:$PORT/api/stores/3/groups/3/kv/delete" \
-H 'Content-Type: application/json' \
-d '{"key":"user:1"}'
curl "http://$IP:$PORT/api/stores/3/groups/3/kv/scan?prefix=user:&limit=100"
The Web UI KV Operator panel provides the same operations with a store/group selector, paginated scan, and inline editing.
3.1 Scan modes
CROWDB provides two range-read modes for different use cases:
- List scan (
kv scan) — the default scan. Fast, always returns the latest value per key at each page's read point. S3-list semantics: each page is independently consistent, but a key can vanish (deleted between pages) or a value can drift (overwritten between pages) within a single logical scan. No server-side state beyond the per-page read barrier. Use for interactive listing, key discovery, and the KV Operator UI. - Snapshot scan (
snapshot create+snapshot scan) — point-in-time-consistent. Pins a frozen view of the keyspace at a specific slot; every page is served from the same frozen view. No key vanishes, no value drifts, no phantom keys appear. Use for backup, analytics, and any consumer that needs a consistent point-in-time view. See §3.2 below.
3.2 Snapshot versioning
A snapshot scan pins a point-in-time view of the keyspace. Creating a snapshot flushes the in-memory write buffer (L0) into the durable tree (L1), then pins L1 at the current applied slot. The snapshot is a frozen, immutable view. Iterating it is pure array traversal with no concurrency concerns. Each snapshot has a server-side handle with a lease (default 5 minutes); the handle is reaped if the client disconnects, preventing unbounded pin retention.
Create a snapshot:
crowdb-cli snapshot create --store-id 3 --group-id 3
# Returns: snapshot_handle=42, at_slot=12345
List active snapshots:
crowdb-cli snapshot list --store-id 3 --group-id 3
# Returns: handle, at_slot, lease_remaining for each active snapshot
Scan a snapshot (paginated, same prefix/start_after/limit as list scan):
# First page
crowdb-cli snapshot scan --store-id 3 --group-id 3 \
--handle 42 --prefix user: --limit 100
# Next page (start_after = last key from previous page)
crowdb-cli snapshot scan --store-id 3 --group-id 3 \
--handle 42 --prefix user: --limit 100 \
--start-after user:50
Release a snapshot (free the pinned pages):
crowdb-cli snapshot release --store-id 3 --group-id 3 --handle 42
curl:
# Create
curl -X POST "http://$IP:$PORT/api/stores/3/groups/3/snapshots"
# List
curl "http://$IP:$PORT/api/stores/3/groups/3/snapshots"
# Scan
curl "http://$IP:$PORT/api/stores/3/groups/3/snapshots/42/scan?prefix=user:&limit=100"
# Release
curl -X DELETE "http://$IP:$PORT/api/stores/3/groups/3/snapshots/42"
GC and snapshots: the engine's garbage collector reclaims tombstones
and stale versions with slot <= gc_watermark. Active snapshots protect
their pinned pages via refcount — GC never frees a page a live snapshot
still references. Once a snapshot is released (or its lease expires), the
next GC sweep can reclaim those pages. The GC watermark can be advanced
explicitly via the management API to control retention:
# Advance GC watermark (data with slot <= watermark becomes reclaimable)
curl -X POST "http://$IP:$PORT/api/stores/3/groups/3/gc-watermark" \
-H 'Content-Type: application/json' \
-d '{"slot":12000}'