@deno/kv

A Deno KV client library optimized for Node.js.
- Access Deno Deploy remote databases (or any
endpoint implementing the open
KV Connect
protocol) on Node 18+.
- Create local KV databases backed by
SQLite, using optimized native
NAPI packages for
Node - compatible with databases created by Deno itself.
- Create ephemeral in-memory KV instances backed by SQLite memory files or by a
lightweight JS-only implementation for testing.
- Zero JS dependencies, architecture-specific native code for SQLite backend
(see below).
- Simply call the exported
openKv
function (equiv to
Deno.openKv
) with a url or
local path to get started!
Quick start - Node 18+
Install the npm package 👉
npm install @deno/kv
Remote KV Database
import { openKv } from "@deno/kv";
const kv = await openKv(
"https://api.deno.com/databases/YOUR_DATABASE_ID/connect",
);
const result = await kv.set(["from-client"], "hello!");
console.log(result);
kv.close();
const kv2 = await openKv(
"https://api.deno.com/databases/YOUR_DATABASE_ID/connect",
{ accessToken: mySecretAccessToken },
);
Local KV Database
import { openKv } from "@deno/kv";
const kv = await openKv("kv.db");
const result = await kv.set(["from-client"], "hello!");
console.log(result);
kv.close();
In-Memory KV Database (no native code)
import { openKv } from "@deno/kv";
const kv = await openKv("");
const result = await kv.set(["from-client"], "hello!");
console.log(result);
kv.close();
Examples use ESM syntax, but this package supports CJS require
-based usage
as well
Local KV Databases
Local disk-based databases are backed by
SQLite, and are compatible with databases created
with Deno itself:
- leverages shared Rust code from
denoland/denokv with a small shim
compiled for Node's native interface via the NAPI-RS
framework
- an architecture-specific native package dependency is selected and installed
at
npm install
time via the standard npm
peer dependency mechanism
The following native architectures are supported:
Windows x64 | ✓ | ✓ |
macOS x64 | ✓ | ✓ |
macOS arm64 | ✓ | ✓ |
Linux x64 gnu | ✓ | ✓ |
Credits
API
This package exports a single convenience function openKv
, taking an optional
string path
, with optional opts
. Depending on the path
provided, one of
three different implementations are used:
- if
path
is omitted or blank, an ephemeral in-memory
db implementation is
used, useful for testing
- if
path
is an http or https url, the remote
client implementation is used
to connect to Deno Deploy or self-hosted
denokv instances
- otherwise the
path
is passed to the native sqlite
implementation - can
specify local paths or :memory:
for SQLite's
in-memory mode
You can override the implementation used via the implementation
option:
const kv = await openKv("https://example.com/not-really-remote", {
implementation: "in-memory",
});
Pass the debug
option to console.log
additional debugging info:
const kv = await openKv("http://localhost:4512/", {
debug: true
});
Backend-specific options
Each implementation supports different additional options,
via the second parameter to openKv
:
Remote backend
export interface RemoteServiceOptions {
readonly accessToken: string;
readonly wrapUnknownValues?: boolean;
readonly debug?: boolean;
readonly encodeV8?: EncodeV8;
readonly decodeV8?: DecodeV8;
readonly fetcher?: Fetcher;
readonly maxRetries?: number;
readonly supportedVersions?: KvConnectProtocolVersion[];
}
Native SQLite backend
export interface NapiBasedServiceOptions {
readonly debug?: boolean;
readonly napi?: NapiInterface;
readonly encodeV8: EncodeV8;
readonly decodeV8: DecodeV8;
readonly inMemory?: boolean;
}
Lightweight In-Memory backend
export interface InMemoryServiceOptions {
readonly debug?: boolean;
readonly maxQueueAttempts?: number;
}
Other runtimes
This package is targeted for Node.js, but may work on other runtimes with the following caveats:
V8 Serialization
Deno KV uses V8's serialization format to serialize values, provided natively by Deno and when using this
package on Node automatically via the built-in v8
module.
Bun also provides a v8
module, but uses a different serialization format under the hood (JavaScriptCore).
This can present data corruption problems if you want to use databases on Deno Deploy or other databases shared
with Node/Deno that use actual V8 serialization: you might create data you cannot read, or vice versa.
For this reason, openKV
on Bun will throw by default to avoid unexpected data corruption.
If you are only going to read and write to your local databases in Bun, you can force the use of Bun's serializers by providing
a custom encodeV8
, decodeV8
explicitly as the second parameter to openKv
. Note any data will be unreadable by
Node (using @deno/kv), or Deno - since they use the actual V8 format.
import { openKv } from "@deno/kv";
import { serialize as encodeV8, deserialize as decodeV8 } from "v8";
const kv = await openKv("kv.db", { encodeV8, decodeV8 });
If a native v8
module is not available on your runtime, you can use a limited JS-based V8 serializer provided by this package.
It only supports a limited number of value types (string
, boolean
, null
, undefined
), so consider using JSON.parse
/JSON.stringify
to marshall values to and from strings for storage.
import { openKv, makeLimitedV8Serializer } from "@deno/kv";
const { encodeV8, decodeV8 } = makeLimitedV8Serializer();
const kv = await openKv("kv.db", { encodeV8, decodeV8 });
V8 serialization is only necessary for SQLite and remote databases, the in-memory implementation
used when calling openKv()
or openKv('')
uses in-process values and structuredClone
instead.