Grafbase KV
Grafbase KV is a simple and fast serverless key-value store for resolvers that is eventually consistent.
This feature is currently experimental and free, for now.
You can enable the experimental KV by adding the following to your grafbase.config.ts
config export object:
export default config({
schema: g,
experimental: {
kv: true,
},
})
Make sure to enable the experimental KV support inside your project's configuration file.
- Import
kv
from thecontext
argument inside a JavaScript or TypeScript resolver:
export default async function MyResolver(_, __, { kv }) {
// ...
}
- Get a value from KV using a custom key:
export default async function MyResolver(_, __, { kv }) {
let { value } = await kv.get('hello')
}
- Set if no value exists:
export default async function MyResolver(_, __, { kv }) {
let { value } = await kv.get('hello')
if (!value) {
value = await kv.set('hello', 'world')
}
return value
}
- Set an optional time-to-live value in seconds:
export default async function MyResolver(_, __, { kv }) {
let { value } = await kv.get('hello')
if (!value) {
value = await kv.set('hello', 'world', { ttl: 3600 })
}
return value
}
You can create a new key-value pair or update an existing value for a key by calling kv.set()
:
export default async function MyResolver(_, __, { kv }) {
const key = '...'
const value = '...'
await kv.set(key, value)
}
You can fetch the value
of a key-value pair at anytime by calling kv.get()
:
export default async function MyResolver(_, __, { kv }) {
const key = '...'
const { value } = await kv.get(key)
}
You can also fetch metadata
for the key-value pair:
export default async function MyResolver(_, __, { kv }) {
const key = '...'
const { metadata } = await kv.get(key)
}
You can fetch a list of all keys anytime by calling kv.list()
:
export default async function MyResolver(_, __, { kv }) {
await kv.list()
}
The object returned by kv.list()
looks something like this:
{
"keys": [
{
"customKey": "customValue",
"expiration": 1696328752,
"metadata": { "someKey": "someValue" }
}
],
"list_complete": false,
"cursor": "6Ck1la0VxJ0djhidm1MdX2FyD"
}
If the list_complete
is false
then you will receive a cursor
value you can pass to list()
to obtain the next set of results.
You can pass values prefix
, limit
and cursor
to kv.list()
:
export default async function MyResolver(_, __, { kv }) {
await kv.list({ prefix, limit, cursor })
}
prefix
is an optionalstring
used to filter all keyslimit
is an optional maxnumber
of keys to returncursor
is an optionalstring
used for paginating responses
Keys are always returned in the order sorted based on their UTF-8 byte values.
To delete a key-value pair you can call kv.delete()
:
export default async function MyResolver(_, __, { kv }) {
const key = '...'
await kv.delete(key)
}
You can store metadata (serialized JSON) on key-value pairs which is also returned by list()
and get()
:
export default async function MyResolver(_, __, { kv }) {
const key = '...'
const value = '...'
const metadata = {
hello: 'world',
}
await kv.set(key, value, { metadata })
}
You can expire key-value pairs by passing a ttl
value (in seconds) when calling kv.set()
:
export default async function MyResolver(_, __, { kv }) {
const key = '...'
const value = '...'
await kv.set(key, value, { ttl: 3600 })
}
The minimum ttl
is 60 seconds.