Key-value
Key-value is the plainest of the five models. A key is bytes, a value is bytes, and you get the value back by naming the key.
strata kv put user:1 alice
strata kv get user:1
alice
Use it when you know the key and want the value, and the value has no structure the database needs to understand. When the shape matters, JSON is the model that can read one field.
The basics
strata kv put user:1 alice
strata kv exists user:1
strata kv count
strata kv delete user:1
A put on an existing key replaces the visible value and records a new version;
it does not fail and there is no separate update. delete removes the key from
view and leaves a tombstone in history, so a deleted key reads as absent while
still being distinguishable from one that was never written.
strata kv get user:1
strata kv exists user:1
(nil)
false
What a write promises
The engine states two guarantees for a KV write, and they are worth knowing because they remove work you might otherwise do yourself.
Atomic per key. The write is a single commit. It applies fully, value plus a new version, or not at all. No reader ever sees a partial or torn value.
Read-after-write visibility. Once the command returns success, every later read through any handle of the same database sees that write or a newer one, including immediately from the handle that issued it. An acknowledged write is never transiently invisible, so there is no window to poll through.
Listing and scanning are different commands
list gives you keys. scan gives you rows: key, value, and the version facts.
strata kv list --prefix user:
user:1
user:2
user:3
strata kv scan --limit 2
{"key":"k:1","timestamp":3,"value":"v1","version":3}
{"key":"k:2","timestamp":4,"value":"v2","version":4}
-- more: add --cursor azoz to the same command
Both take --prefix. Reach for list when you only need to know what is there,
because it does not carry the values back.
Pagination hands you the cursor
A truncated scan tells you how to continue, and you pass that value straight
back:
strata kv scan --limit 2 --cursor azoz
The cursor is opaque. It looks like base64 and it sometimes decodes to something recognisable, but the engine’s contract is that you pass it back unmodified and never parse it. Treat it as a token, not as a key.
sample is the other way to look at a lot of keys, when you want a few
arbitrary rows rather than an ordered page:
strata kv sample --count 2
History and reading the past
Every version of a key is retained, newest first:
strata kv history k:1
{"timestamp":8,"tombstone":false,"value":"v1-updated","version":8}
{"timestamp":3,"tombstone":false,"value":"v1","version":3}
And any read can be taken at a point on the timeline:
strata kv get k:1 --as-of 3
v1
Pass the timestamp from the history output, not the version.
Time travel is the page for why those are different
numbers and what happens if you confuse them.
Two things that surprise people
Batch operations are not CLI verbs. There is no strata kv batch-put. The
batch commands exist in the engine and are reachable from the SDK or through the
command escape hatch, and all the entries land in one commit:
strata command run --command-json '{"entries":[{"key":"YQ==","value":"MQ=="},{"key":"Yg==","value":"Mg=="}],"type":"kv_batch_put"}'
Both results in that response carry the same version, which is the point of a
batch: several keys, one commit, one version.
Values that are not valid UTF-8 come back base64-encoded, and nothing says so. Writing arbitrary bytes is well supported:
strata kv put raw --file ./payload.bin
Reading them back is where it gets sharp. A value the terminal can print comes
back as text. A value it cannot comes back as base64, on the default output, on
--raw, and inside --json alike:
strata kv get raw
AAH/
The bytes are intact and decoding by hand recovers them exactly. But no CLI flag
returns the raw bytes, and no marker distinguishes a value that happens to read
as AAH/ from one that was encoded. If you store binary through the CLI, decode
on the way out and know that you are doing it.
Where to look next
Every KV command, with its parameters, return shape and error codes, is in the key-value reference.