Skip to main content
class Deno.Kv
implements Disposable
Unstable

A key-value database that can be used to store and retrieve data.

Data is stored as key-value pairs, where the key is a Deno.KvKey and the value is an arbitrary structured-serializable JavaScript value. Keys are ordered lexicographically as described in the documentation for Deno.KvKey. Keys are unique within a database, and the last value set for a given key is the one that is returned when reading the key. Keys can be deleted from the database, in which case they will no longer be returned when reading keys.

Values can be any structured-serializable JavaScript value (objects, arrays, strings, numbers, etc.). The special value Deno.KvU64 can be used to store 64-bit unsigned integers in the database. This special value can not be nested within other objects or arrays. In addition to the regular database mutation operations, the unsigned 64-bit integer value also supports sum, max, and min mutations.

Keys are versioned on write by assigning the key an ever-increasing "versionstamp". The versionstamp represents the version of a key-value pair in the database at some point in time, and can be used to perform transactional operations on the database without requiring any locking. This is enabled by atomic operations, which can have conditions that ensure that the operation only succeeds if the versionstamp of the key-value pair matches an expected versionstamp.

Keys have a maximum length of 2048 bytes after serialization. Values have a maximum length of 64 KiB after serialization. Serialization of both keys and values is somewhat opaque, but one can usually assume that the serialization of any value is about the same length as the resulting string of a JSON serialization of that same value. If theses limits are exceeded, an exception will be thrown.

Methods

Create a new Deno.AtomicOperation object which can be used to perform an atomic transaction on the database. This does not perform any operations on the database - the atomic transaction must be committed explicitly using the Deno.AtomicOperation.commit method once all checks and mutations have been added to the operation.

close(): void

Close the database connection. This will prevent any further operations from being performed on the database, and interrupt any in-flight operations immediately.

Get a symbol that represents the versionstamp of the current atomic operation. This symbol can be used as the last part of a key in .set(), both directly on the Kv object and on an AtomicOperation object created from this Kv instance.

delete(key: KvKey): Promise<void>

Delete the value for the given key from the database. If no value exists for the key, this operation is a no-op.

const db = await Deno.openKv();
await db.delete(["foo"]);
enqueue(value: unknown, options?: { delay?: number; keysIfUndelivered?: Deno.KvKey[]; backoffSchedule?: number[]; }): Promise<KvCommitResult>

Add a value into the database queue to be delivered to the queue listener via Deno.Kv.listenQueue.

const db = await Deno.openKv();
await db.enqueue("bar");

The delay option can be used to specify the delay (in milliseconds) of the value delivery. The default delay is 0, which means immediate delivery.

const db = await Deno.openKv();
await db.enqueue("bar", { delay: 60000 });

The keysIfUndelivered option can be used to specify the keys to be set if the value is not successfully delivered to the queue listener after several attempts. The values are set to the value of the queued message.

The backoffSchedule option can be used to specify the retry policy for failed message delivery. Each element in the array represents the number of milliseconds to wait before retrying the delivery. For example, [1000, 5000, 10000] means that a failed delivery will be retried at most 3 times, with 1 second, 5 seconds, and 10 seconds delay between each retry.

const db = await Deno.openKv();
await db.enqueue("bar", {
  keysIfUndelivered: [["foo", "bar"]],
  backoffSchedule: [1000, 5000, 10000],
});
get<T = unknown>(key: KvKey, options?: { consistency?: KvConsistencyLevel; }): Promise<KvEntryMaybe<T>>

Retrieve the value and versionstamp for the given key from the database in the form of a Deno.KvEntryMaybe. If no value exists for the key, the returned entry will have a null value and versionstamp.

const db = await Deno.openKv();
const result = await db.get(["foo"]);
result.key; // ["foo"]
result.value; // "bar"
result.versionstamp; // "00000000000000010000"

The consistency option can be used to specify the consistency level for the read operation. The default consistency level is "strong". Some use cases can benefit from using a weaker consistency level. For more information on consistency levels, see the documentation for Deno.KvConsistencyLevel.

getMany<T extends readonly unknown[]>(keys: readonly [...[K in keyof T]: KvKey], options?: { consistency?: KvConsistencyLevel; }): Promise<[K in keyof T]: KvEntryMaybe<T[K]>>

Retrieve multiple values and versionstamps from the database in the form of an array of Deno.KvEntryMaybe objects. The returned array will have the same length as the keys array, and the entries will be in the same order as the keys. If no value exists for a given key, the returned entry will have a null value and versionstamp.

const db = await Deno.openKv();
const result = await db.getMany([["foo"], ["baz"]]);
result[0].key; // ["foo"]
result[0].value; // "bar"
result[0].versionstamp; // "00000000000000010000"
result[1].key; // ["baz"]
result[1].value; // null
result[1].versionstamp; // null

The consistency option can be used to specify the consistency level for the read operation. The default consistency level is "strong". Some use cases can benefit from using a weaker consistency level. For more information on consistency levels, see the documentation for Deno.KvConsistencyLevel.

list<T = unknown>(selector: KvListSelector, options?: KvListOptions): KvListIterator<T>

Retrieve a list of keys in the database. The returned list is an Deno.KvListIterator which can be used to iterate over the entries in the database.

Each list operation must specify a selector which is used to specify the range of keys to return. The selector can either be a prefix selector, or a range selector:

  • A prefix selector selects all keys that start with the given prefix of key parts. For example, the selector ["users"] will select all keys that start with the prefix ["users"], such as ["users", "alice"] and ["users", "bob"]. Note that you can not partially match a key part, so the selector ["users", "a"] will not match the key ["users", "alice"]. A prefix selector may specify a start key that is used to skip over keys that are lexicographically less than the start key.
  • A range selector selects all keys that are lexicographically between the given start and end keys (including the start, and excluding the end). For example, the selector ["users", "a"], ["users", "n"] will select all keys that start with the prefix ["users"] and have a second key part that is lexicographically between a and n, such as ["users", "alice"], ["users", "bob"], and ["users", "mike"], but not ["users", "noa"] or ["users", "zoe"].
const db = await Deno.openKv();
const entries = db.list({ prefix: ["users"] });
for await (const entry of entries) {
  entry.key; // ["users", "alice"]
  entry.value; // { name: "Alice" }
  entry.versionstamp; // "00000000000000010000"
}

The options argument can be used to specify additional options for the list operation. See the documentation for Deno.KvListOptions for more information.

listenQueue(handler: (value: any) => Promise<void> | void): Promise<void>

Listen for queue values to be delivered from the database queue, which were enqueued with Deno.Kv.enqueue. The provided handler callback is invoked on every dequeued value. A failed callback invocation is automatically retried multiple times until it succeeds or until the maximum number of retries is reached.

const db = await Deno.openKv();
db.listenQueue(async (msg: unknown) => {
  await db.set(["foo"], msg);
});
set(
key: KvKey,
value: unknown,
options?: { expireIn?: number; },
): Promise<KvCommitResult>

Set the value for the given key in the database. If a value already exists for the key, it will be overwritten.

const db = await Deno.openKv();
await db.set(["foo"], "bar");

Optionally an expireIn option can be specified to set a time-to-live (TTL) for the key. The TTL is specified in milliseconds, and the key will be deleted from the database at earliest after the specified number of milliseconds have elapsed. Once the specified duration has passed, the key may still be visible for some additional time. If the expireIn option is not specified, the key will not expire.

watch<T extends readonly unknown[]>(keys: readonly [...[K in keyof T]: KvKey], options?: { raw?: boolean; }): ReadableStream<[K in keyof T]: KvEntryMaybe<T[K]>>

Watch for changes to the given keys in the database. The returned stream is a ReadableStream that emits a new value whenever any of the watched keys change their versionstamp. The emitted value is an array of Deno.KvEntryMaybe objects, with the same length and order as the keys array. If no value exists for a given key, the returned entry will have a null value and versionstamp.

The returned stream does not return every single intermediate state of the watched keys, but rather only keeps you up to date with the latest state of the keys. This means that if a key is modified multiple times quickly, you may not receive a notification for every single change, but rather only the latest state of the key.

const db = await Deno.openKv();

const stream = db.watch([["foo"], ["bar"]]);
for await (const entries of stream) {
  entries[0].key; // ["foo"]
  entries[0].value; // "bar"
  entries[0].versionstamp; // "00000000000000010000"
  entries[1].key; // ["bar"]
  entries[1].value; // null
  entries[1].versionstamp; // null
}

The options argument can be used to specify additional options for the watch operation. The raw option can be used to specify whether a new value should be emitted whenever a mutation occurs on any of the watched keys (even if the value of the key does not change, such as deleting a deleted key), or only when entries have observably changed in some way. When raw: true is used, it is possible for the stream to occasionally emit values even if no mutations have occurred on any of the watched keys. The default value for this option is false.

Methods

Create a new Deno.AtomicOperation object which can be used to perform an atomic transaction on the database. This does not perform any operations on the database - the atomic transaction must be committed explicitly using the Deno.AtomicOperation.commit method once all checks and mutations have been added to the operation.

close(): void

Close the database connection. This will prevent any further operations from being performed on the database, and interrupt any in-flight operations immediately.

Get a symbol that represents the versionstamp of the current atomic operation. This symbol can be used as the last part of a key in .set(), both directly on the Kv object and on an AtomicOperation object created from this Kv instance.

delete(key: KvKey): Promise<void>

Delete the value for the given key from the database. If no value exists for the key, this operation is a no-op.

const db = await Deno.openKv();
await db.delete(["foo"]);
enqueue(value: unknown, options?: { delay?: number; keysIfUndelivered?: Deno.KvKey[]; backoffSchedule?: number[]; }): Promise<KvCommitResult>

Add a value into the database queue to be delivered to the queue listener via Deno.Kv.listenQueue.

const db = await Deno.openKv();
await db.enqueue("bar");

The delay option can be used to specify the delay (in milliseconds) of the value delivery. The default delay is 0, which means immediate delivery.

const db = await Deno.openKv();
await db.enqueue("bar", { delay: 60000 });

The keysIfUndelivered option can be used to specify the keys to be set if the value is not successfully delivered to the queue listener after several attempts. The values are set to the value of the queued message.

The backoffSchedule option can be used to specify the retry policy for failed message delivery. Each element in the array represents the number of milliseconds to wait before retrying the delivery. For example, [1000, 5000, 10000] means that a failed delivery will be retried at most 3 times, with 1 second, 5 seconds, and 10 seconds delay between each retry.

const db = await Deno.openKv();
await db.enqueue("bar", {
  keysIfUndelivered: [["foo", "bar"]],
  backoffSchedule: [1000, 5000, 10000],
});
get<T = unknown>(key: KvKey, options?: { consistency?: KvConsistencyLevel; }): Promise<KvEntryMaybe<T>>

Retrieve the value and versionstamp for the given key from the database in the form of a Deno.KvEntryMaybe. If no value exists for the key, the returned entry will have a null value and versionstamp.

const db = await Deno.openKv();
const result = await db.get(["foo"]);
result.key; // ["foo"]
result.value; // "bar"
result.versionstamp; // "00000000000000010000"

The consistency option can be used to specify the consistency level for the read operation. The default consistency level is "strong". Some use cases can benefit from using a weaker consistency level. For more information on consistency levels, see the documentation for Deno.KvConsistencyLevel.

getMany<T extends readonly unknown[]>(keys: readonly [...[K in keyof T]: KvKey], options?: { consistency?: KvConsistencyLevel; }): Promise<[K in keyof T]: KvEntryMaybe<T[K]>>

Retrieve multiple values and versionstamps from the database in the form of an array of Deno.KvEntryMaybe objects. The returned array will have the same length as the keys array, and the entries will be in the same order as the keys. If no value exists for a given key, the returned entry will have a null value and versionstamp.

const db = await Deno.openKv();
const result = await db.getMany([["foo"], ["baz"]]);
result[0].key; // ["foo"]
result[0].value; // "bar"
result[0].versionstamp; // "00000000000000010000"
result[1].key; // ["baz"]
result[1].value; // null
result[1].versionstamp; // null

The consistency option can be used to specify the consistency level for the read operation. The default consistency level is "strong". Some use cases can benefit from using a weaker consistency level. For more information on consistency levels, see the documentation for Deno.KvConsistencyLevel.

list<T = unknown>(selector: KvListSelector, options?: KvListOptions): KvListIterator<T>

Retrieve a list of keys in the database. The returned list is an Deno.KvListIterator which can be used to iterate over the entries in the database.

Each list operation must specify a selector which is used to specify the range of keys to return. The selector can either be a prefix selector, or a range selector:

  • A prefix selector selects all keys that start with the given prefix of key parts. For example, the selector ["users"] will select all keys that start with the prefix ["users"], such as ["users", "alice"] and ["users", "bob"]. Note that you can not partially match a key part, so the selector ["users", "a"] will not match the key ["users", "alice"]. A prefix selector may specify a start key that is used to skip over keys that are lexicographically less than the start key.
  • A range selector selects all keys that are lexicographically between the given start and end keys (including the start, and excluding the end). For example, the selector ["users", "a"], ["users", "n"] will select all keys that start with the prefix ["users"] and have a second key part that is lexicographically between a and n, such as ["users", "alice"], ["users", "bob"], and ["users", "mike"], but not ["users", "noa"] or ["users", "zoe"].
const db = await Deno.openKv();
const entries = db.list({ prefix: ["users"] });
for await (const entry of entries) {
  entry.key; // ["users", "alice"]
  entry.value; // { name: "Alice" }
  entry.versionstamp; // "00000000000000010000"
}

The options argument can be used to specify additional options for the list operation. See the documentation for Deno.KvListOptions for more information.

listenQueue(handler: (value: any) => Promise<void> | void): Promise<void>

Listen for queue values to be delivered from the database queue, which were enqueued with Deno.Kv.enqueue. The provided handler callback is invoked on every dequeued value. A failed callback invocation is automatically retried multiple times until it succeeds or until the maximum number of retries is reached.

const db = await Deno.openKv();
db.listenQueue(async (msg: unknown) => {
  await db.set(["foo"], msg);
});
set(
key: KvKey,
value: unknown,
options?: { expireIn?: number; },
): Promise<KvCommitResult>

Set the value for the given key in the database. If a value already exists for the key, it will be overwritten.

const db = await Deno.openKv();
await db.set(["foo"], "bar");

Optionally an expireIn option can be specified to set a time-to-live (TTL) for the key. The TTL is specified in milliseconds, and the key will be deleted from the database at earliest after the specified number of milliseconds have elapsed. Once the specified duration has passed, the key may still be visible for some additional time. If the expireIn option is not specified, the key will not expire.

watch<T extends readonly unknown[]>(keys: readonly [...[K in keyof T]: KvKey], options?: { raw?: boolean; }): ReadableStream<[K in keyof T]: KvEntryMaybe<T[K]>>

Watch for changes to the given keys in the database. The returned stream is a ReadableStream that emits a new value whenever any of the watched keys change their versionstamp. The emitted value is an array of Deno.KvEntryMaybe objects, with the same length and order as the keys array. If no value exists for a given key, the returned entry will have a null value and versionstamp.

The returned stream does not return every single intermediate state of the watched keys, but rather only keeps you up to date with the latest state of the keys. This means that if a key is modified multiple times quickly, you may not receive a notification for every single change, but rather only the latest state of the key.

const db = await Deno.openKv();

const stream = db.watch([["foo"], ["bar"]]);
for await (const entries of stream) {
  entries[0].key; // ["foo"]
  entries[0].value; // "bar"
  entries[0].versionstamp; // "00000000000000010000"
  entries[1].key; // ["bar"]
  entries[1].value; // null
  entries[1].versionstamp; // null
}

The options argument can be used to specify additional options for the watch operation. The raw option can be used to specify whether a new value should be emitted whenever a mutation occurs on any of the watched keys (even if the value of the key does not change, such as deleting a deleted key), or only when entries have observably changed in some way. When raw: true is used, it is possible for the stream to occasionally emit values even if no mutations have occurred on any of the watched keys. The default value for this option is false.