db.kv(name) is a store of bytes, one per character. substrio.kv(name) is the same.
const kv = db.kv("sessions");
kv.put("a", "hello"); // true
kv.get("a"); // "hello"
kv.peek("a"); // 5 (stored length in bytes), -1 when absent
kv.delete("a"); // true
Values
A value is a string of characters up to U+00FF, a number, a boolean, a BigInt or
binary data (Uint8Array, ArrayBuffer). get answers a string of the stored
bytes: put("n", 5) then get("n") is "5". Text with other characters throws
a TypeError. Store text as UTF-8 bytes and decode it:
kv.put("t", new TextEncoder().encode("héllo ✓"));
const text = new TextDecoder().decode(Uint8Array.from(kv.get("t"), (c) => c.charCodeAt(0)));
A key is a string under the same rule: characters up to U+00FF. A key with a
wider character throws a TypeError (kv.getInt: the key has a character above U+00FF; KV stores one byte per character, so pass bytes ...); a key that is not
a string throws kv.<method>: the key must be .... Encode text keys the way
the example above encodes values.
Reading: what each form allocates
| Call | Allocates |
|---|---|
get(key) |
one string (the value is copied once into it) |
getBytes(key) |
one Uint8Array (one copy); keep it as long as you like |
ref(key) |
nothing; the value lands in the store's _v buffer and is valid until the next ref |
peek(key), has(key) |
nothing (peek answers the length, has a boolean, neither reads the value) |
getInt(key), getF64(key) |
nothing |
kv.has("a"); // true or false
const bytes = kv.getBytes("a"); // Uint8Array [104, 101, ...], null when absent
const n = kv.ref("a"); // 5; read kv._v.subarray(0, n) before the next ref
Numbers
kv.putInt("count", 41); // true: an integer, exact within the safe range
kv.getInt("count"); // 41, undefined when absent
kv.putF64("ratio", 0.5); // true
kv.getF64("ratio"); // 0.5, undefined when absent
putInt takes only a number that is an integer within -(2^53 - 1) to 2^53 - 1.
A fraction, NaN, an infinity, a number outside that range, a BigInt, a string or
a missing value throws a TypeError (kv.putInt: the value must be an integer within the safe integer range ..., or ... must be a number). putF64 takes
any number and throws the same must be a number TypeError for anything else.
Nothing a refused write was given is stored.
getInt and getF64 answer undefined for an absent key and for a stored value
that is not 8 bytes. getInt never answers a BigInt: a stored integer outside
the safe range throws a RangeError (kv.getInt: the value stored is an integer outside the safe integer range ...). Both kinds are the same 8 bytes, so read a
value with the kind that wrote it: getInt on a putF64 value reinterprets the
bytes (putF64(5e-324) reads as the integer 1, and most doubles throw the
RangeError).
kv.increment("hits"); // 1: an absent key starts at 0, then adds 1
kv.increment("hits", 5); // 6: atomic, safe from concurrent calls
A counter is an 8-byte integer: getInt reads it. increment answers undefined
when the stored value is not 8 bytes, and throws when the result leaves the safe range.
Cursor
const cursor = kv.cursor();
for (let ok = cursor.seekPrefix("user:"); ok; ok = cursor.next()) {
const key = cursor.key(); // string
const value = cursor.value(); // string
}
cursor.close();
Also seekFirst, seekLast, seekGE, seekLE, seekLT, seekPrefixLast, prev
and scanCount(prefix?).
A seekPrefix (or seekPrefixLast) prefix stays the cursor's filter until its next
seekFirst, seekLast, seekPrefix or seekPrefixLast: a later seekGE, seekLE or
seekLT positions inside that prefix, and next/prev stop at its end. A seekGE to a
key outside it finds nothing. Code that walks prefixes and also seeks by key keeps a cursor
for each, or calls seekFirst before the key seek.
Limits and rules
- A key is at most 65535 bytes; a longer one throws an error naming the size and the limit (
kv.put: key of N bytes exceeds the limit of 65535 bytes). - One value is at most 16 MiB; a larger one throws an error naming the size and the limit (
kv.put: single value of N bytes exceeds the limit of 16777216 bytes). - A write inside
db.transactionthrows (kv is not transactional): write outside it. - The Cloudflare shim
env.<KV>hasget,put,deleteandlist; its options are ignored andlistis unreliable. Preferdb.kv.