A self-hosted backend for Deno KV

Overview

denokv

A self-hosted backend for Deno KV, the JavaScript first key-value database:

  • Seamlessly integrated JavaScript APIs
  • ACID transactions
  • Multiple consistency levels for optimal performance for every usecase

Diagram showing how a denokv setup looks Diagram showing how a denokv setup looks

Deno KV can be used with the built-in single instance database in the CLI, useful for testing and development, with a hosted and scalable backend on Deno Deploy, or with this self-hostable Deno KV backend.

To run denokv, just run:

docker run -it --init -p 4512:4512 -v ./data:/data ghcr.io/denoland/denokv --sqlite-path /data/denokv.sqlite serve --access-token <random-token>

Then run your Deno program and specify the access token in the DENO_KV_ACCESS_TOKEN environment variable:

const kv = await Deno.openKv("http://localhost:4512");

The self-hosted denokv backend is built on the same robust SQLite backend as the built-in single instance database in the CLI. It is designed to be run on a VPS or Kubernetes cluster statefully, with Deno processes connecting via the network using KV Connect.

The standalone denokv binary is designed to handle thousands of concurrent requests, from hundreds of different Deno processes. It is built on top of the robust SQLite database, and uses non-blocking IO to ensure excellent performance even in the face of hundreds of concurrent connections.

Just like the Deno CLI, denokv is MIT licensed, free and open source.

Read more in the announcement of self-hosted Deno KV.

When should I use this?

If you need more than a single Deno process to access the same KV database, and you are ok with running a server, keeping denokv updated, handling backups, and performing regular maintenance, then this is for you.

You can use a hosted KV database on Deno Deploy if you don't want to self-host and manage a denokv server.

If you are just need a backend for local development or testing, you can use the Deno KV backend built into the Deno CLI. You can open a temporary in memory KV database with Deno.openKv(":memory:") or a persistent database by specifying a path like Deno.openKv("./my-database.sqlite").

How to run

Docker on a VPS

Ensure that you are running on a service that supports persistent storage, and does not perform auto-scaling beyond a single instance. This means you can not run denokv on Google Cloud Run or AWS Lambda.

Install Docker on your VPS and create a directory for the database to store data in.

$ mkdir -p /data

Then run the denokv Docker image, mounting the /data directory as a volume and specifying a random access token.

docker run -it --init -p 4512:4512 -v ./data:/data ghcr.io/denoland/denokv --sqlite-path /data/denokv.sqlite serve --access-token <random-token>

You can now access the database from your Deno programs by specifying the access token in the DENO_KV_ACCESS_TOKEN environment variable, and the host and port of your VPS in the URL passed to Deno.openKv.

You should additionally add a HTTPS terminating proxy or loadbalancer in front of denokv to ensure that all communication happens over TLS. Not using TLS can pose a significant security risk. The HTTP protocol used by Deno KV is compatible with any HTTP proxy, such as caddy, nginx, or a loadbalancer.

Fly.io

You can easily host denokv on https://fly.io.

Note: Fly.io is a paid service. You will need to add a credit card to your account to use it.

Sign up to Fly.io and install the flyctl CLI.

Sign into the CLI with flyctl auth login.

Create a new app with flyctl apps create.

Create a fly.toml file with the following contents. Make sure to replace the <your-app-name> and <region> placeholders with your app name and the region you want to deploy to.

app = "<your-app-name>"
primary_region = "<region>"

[build]
  image = "ghcr.io/denoland/denokv:latest"

[http_service]
  internal_port = 4512
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 0

[env]
  DENO_KV_SQLITE_PATH="/data/denokv.sqlite3"
  # access token is set via `flyctl secrets set`

[mounts]
  destination = "/data"
  source = "denokv_data"

Run flyctl volumes create denokv_data to create a volume to store the database in.

Run flyctl secrets set DENO_KV_ACCESS_TOKEN=<random-token> to set the access token. Make sure to replace <random-token> with a random string. Keep this token secret, and don't share it with anyone. You will need this token to connect to your database from Deno.

Run flyctl deploy to deploy your app.

You can now access the database from your Deno programs by specifying the access token in the DENO_KV_ACCESS_TOKEN environment variable, and the URL provided by flyctl deploy in the URL passed to Deno.openKv.

Be aware that with this configuration, your database can scale to 0 instances when not in use. This means that the first request to your database after a period of inactivity will be slow, as the database needs to be started. You can avoid this by setting min_machines_running to 1, and setting auto_stop_machines = false.

Install binary

You can download a prebuilt binary from the releases page and place it in your PATH.

You can also compile from source by running cargo install denokv --locked.

How to connect

Deno

To connect to a denokv server from Deno, use the Deno.openKv API:

const kv = await Deno.openKv("http://localhost:4512");

Make sure to specify your access token in the DENO_KV_ACCESS_TOKEN environment variable.

Advanced setup

Running as a replica of a hosted KV database

denokv has a mode for running as a replica of a KV database hosted on Deno Deploy through the S3 backup feature.

To run as a replica:

docker run -it --init -p 4512:4512 -v ./data:/data \
  -e AWS_ACCESS_KEY_ID="<aws-access-key-id>" \
  -e AWS_SECRET_ACCESS_KEY="<aws-secret-access-key>" \
  -e AWS_REGION="<aws-region>" \
  ghcr.io/denoland/denokv --sqlite-path /data/denokv.sqlite serve \
  --access-token <random-token> --sync-from-s3 --s3-bucket your-bucket --s3-prefix some-prefix/6aea9765-2b1e-41c7-8904-0bdcd70b21d3/

To sync the local database from S3, without updating the snapshot:

denokv --sqlite-path /data/denokv.sqlite pitr sync --s3-bucket your-bucket --s3-prefix some-prefix/6aea9765-2b1e-41c7-8904-0bdcd70b21d3/

To list recoverable points:

denokv --sqlite-path /data/denokv.sqlite pitr list

To checkout the snapshot at a specific recoverable point:

denokv --sqlite-path /data/denokv.sqlite pitr checkout 0100000002c0f4c10000

Continuous backup using LiteFS

TODO

Other things in this repo

This repository contains two crates:

  • denokv_proto (/proto): Shared interfaces backing KV, like definitions of Key, Database, and Value.
  • denokv_sqlite (/sqlite): An implementation of Database backed by SQLite.
  • denokv_remote (/remote): An implementation of Database backed by a remote KV database, acessible via the KV Connect protocol.

These crates are used by the deno_kv crate in the Deno repository to provide a JavaScript API for interacting with Deno KV.

The Deno KV Connect protocol used for communication between Deno and a remote KV database is defined in /proto/kv-connect.md.

Comments
  • `denokv serve`: `500 An internal server error occurred` when attempting to sum a non kvu64

    `denokv serve`: `500 An internal server error occurred` when attempting to sum a non kvu64

    To reproduce: run denokv serve locally, connect via Deno.openKv, then attempt a sum operation on an existing non kvu64 value.

    Expected: http 4xx response, this is a non-retryable client error

    Actual: An error is logged: [ERROR denokv] Failed to write to database: Failed to perform 'sum' mutation on a non-U64 value in the database and an http 500 is returned to the client with body An internal server error occurred. The spec encourages retrying 5xx, so it's probably important to return a 4xx here instead.

    opened by johnspurlock-skymethod 3
  • Rewrite the Deno KV implementation

    Rewrite the Deno KV implementation

    This commit rewrites the KV implementation in CLI.

    The core of this rewrite is that all SQLite operations now synchronously run from a single thread, and the sqlite connection is pinned to this thread. This cleans up the messy coordination using mutexes and spawn_blocking that we were doing previously.

    • We now handle opening of the same SQLite database across multiple processes correctly when using queues.
      • Duplicate queue delivery across multiple processes when one process starts while another is handling an event is now fixed by actually using and setting the deadline attribute in the queue_running table.
    opened by lucacasonato 2
  • Update docs: unexpected argument '--sqlite-path' found when following examples

    Update docs: unexpected argument '--sqlite-path' found when following examples

    When following documentation, I am trying to use the denokv standalone and am getting

    error: unexpected argument '--sqlite-path' found
    
    Usage: denokv --sqlite-path <SQLITE_PATH> serve [OPTIONS] --access-token <ACCESS_TOKEN>
    
    For more information, try '--help'.
    

    This is when running with either installing with cargo or the docker container, reproduce with:

    export DENO_KV_ACCESS_TOKEN=$(openssl rand -base64 15)
    docker run -it --init -p 4512:4512 -v ./data:/data ghcr.io/denoland/denokv serve --sqlite-path /data/denokv.sqlite serve --access-token $DENO_KV_ACCESS_TOKEN
    

    --sqlite-path has to be before serve, docs need to be updated

    opened by john-pope 1
  • chore: make SqliteMessageHandle methods public

    chore: make SqliteMessageHandle methods public

    We need these methods for the NPM module. QueueMessageHandle interface has #[async_trait::async_trait(?Send)], so it can't be used with multithreaded tokio runtime.

    opened by igorzi 0
  • feat: add standalone SQLite backed denokv server

    feat: add standalone SQLite backed denokv server

    This is a standalone Deno KV server backed by SQLite. It exposes a HTTP API that implements the KV Connect protocol and can be used from the Deno CLI.

    The server can be connected to from multiple clients at the same time, which enables a simple way to self host a production ready Deno KV database.

    opened by lucacasonato 0
Releases(0.2.0)
Backend service to build customer facing dashboards 10x faster. Written in Rust.

Frolic is an open source backend service (written in Rust) to build customer facing dashboards 10x faster. You can directly connect your database to t

Frolic 133 Aug 22, 2023
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
Redirect Deno dependencies from semantic versions to the newest fitting version on deno.land/x

Deno Semver Redirect Redirect Deno dependencies from semantic versions to the newest fitting version on deno.land/x. See also this Deno Issue. How to

EdJoPaTo 8 Mar 12, 2022
A (self hosted) pastebin for easily sharing text right from the terminal

termpad termpad allows you to easily host a pastebin server for saving and viewing text right from the terminal, or the browser. Client Usage Assuming

Spyros Roum 28 Aug 29, 2022
Rustpad is an efficient and minimal collaborative code editor, self-hosted, no database required

Rustpad is an efficient and minimal open-source collaborative text editor based on the operational transformation algorithm

Eric Zhang 2.5k Dec 31, 2022
A self-hosted Fuzzing-As-A-Service platform

OneFuzz A self-hosted Fuzzing-As-A-Service platform Project OneFuzz enables continuous developer-driven fuzzing to proactively harden software prior t

Microsoft 2.6k Dec 30, 2022
🎧 a self-hosted Spotify → Discord music bot

Aoede is a Discord music bot that directly streams from Spotify to Discord. The only interface is Spotify itself. Note: a Spotify Premium account is c

Max Isom 159 Dec 29, 2022
Octopus Linguistics for self-hosted runners

octoling Octopus Linguistics for self-hosted runners. Early PoC Allows to create self-hosted ephemeral runners on various providers. (currently only s

Mary 5 Nov 1, 2021
A self-hosted Fuzzing-As-A-Service platform

OneFuzz A self-hosted Fuzzing-As-A-Service platform Project OneFuzz enables continuous developer-driven fuzzing to proactively harden software prior t

Microsoft 2.6k Jan 8, 2023
Jotsy is a self-hosted, free and open-source note taking app with a goal of simplicity in mind

Jotsy: Just your notes Jotsy is a self-hosted, free and open-source note taking app with a goal of simplicity in mind. It is powered by Skytable. Read

Sayan 433 Dec 30, 2022
Self-Hosted alternative to GitHub Gists

Gists Self-Hosted GitHub Gists Features Upload code snippets Syntax Highlighting Comments Versioning through Git Fork gists Gist privacy: public, unli

Aravinth Manivannan 52 Dec 22, 2022
Self-Hosted alternative to GitHub Gists

GitPad Self-Hosted GitHub Gists Features Upload code snippets(✓ REST API) Syntax Highlighting Comments Versioning through Git Fork gists Gist privacy:

Aravinth Manivannan 52 Dec 22, 2022
Manage self-hosted Supabase instances with an easy to use API & Web Portal (soon)

SupaManager A project by Harry Bairstow; Manage self-hosted Supabase instances with an easy to use API & Web Portal (soon) ⚠️ Note: The project is in

Harry Bairstow 11 Sep 15, 2022
Self-hosted, fast, and efficient replacement for ngrok, built with Rust

reverse-proxy reverse-proxy is a self-hosted, fast, and efficient replacement for ngrok, built with Rust. The project leverages the power of Tokio and

null 4 May 22, 2023
Temporary elevated access management as a self-hosted service

????☁️ S A T O U N K I Temporary elevated access management as a self-hosted service Overview Satounki is a self-hosted service which brings visibilit

جاد 31 Dec 17, 2023
A render-backend independant egui backend for sdl2

A Sdl2 + Egui Backend An egui backend for sdl2 unbound to any renderer-backend. You can include it like so: [dependencies] egui_sdl2_platform = "0.1.0

null 4 Dec 16, 2022
A web service that generates images of dependency graphs for crates hosted on crates.io

crate-deps A web service that generates images of dependency graphs for crates hosted on crates.io This project is built entirely in Rust using these

Corey Farwell 20 Nov 9, 2020
A pure-Rust serverless discord chatbot hosted on Cloudflare Workers.

About A pure-Rust serverless discord chatbot hosted on Cloudflare Workers. With a free account you have up to 100k requests per day. For storing state

Mike Dallas 31 Nov 21, 2022
Deno Foreign Function Interface.

deno_plugin_ffi (WIP & Need Help) Deno Foreign Function Interface. deno_ffi is a Deno plugin for loading and calling dynamic libraries using pure Java

Deno Foreign Function Interface 37 Aug 18, 2022
On-the-fly machine code executing from Deno

jit from js Execute raw machine code from JavaScript. I hope you know what you're doing :) const inst = new Uint8Array([0xC3]); // ret const noop = ji

Divy Srivastava 5 Apr 26, 2021