Real-time applications with Deno KV

javascript3 min

byLucas Santos

This page was machine translated. Read original / Suggest a fix

Real-time applications have always been a big problem for most developers, mainly because they follow a paradigm quite different from what we’re used to working with.

Because of that, most applications that needed some kind of real-time communication ended up going in the direction of WebSockets, which are a bit harder to implement, so we’d generally resort to long polling when we weren’t in a rush to receive updates.

Deno once again innovated quite a bit in terms of what can be done with the runtime and applications, making it much easier to create real-time applications.

KV Watch#

A while back I published an article here talking about Deno’s new key-value database, Deno KV.

Just to refresh our memory on what KV is. It’s a database in the key-value model, meaning we don’t have structures like tables and so on. Most of our logical operations are done on top of values stored in keys that follow a textual pattern. For example, the likes on a post with ID 1234 could be represented by a number stored in the key posts:1234:likes.

KV has several really interesting APIs, like queues and cron, but the one that makes all of this possible is watch.

With this new API, Deno KV can observe real-time changes in keys, so whenever one of these keys changes, we can emit an event somewhere notifying about that change.

The new API works through an async iterator that will return the new value of the observed key:

const db = await Deno.openKv()
const stream = db.watch(["chave1"], ["chave", "2"])
for await (const entries of stream) {
entries[0] // { key: ['chave1'], value: 'v', versionstamp: ... }
entries[1] // the same but with key 2
}

Building real-time applications#

Since the idea of this article is to be short and direct, I won’t fully show you how we can build a real-time application here, but I’ll give you an example of how we can work with this new tool.

Server-Sent Events#

The most common thing when we’re building real-time applications on the frontend is to try to create some kind of persistent connection between client and server. In fact, that’s probably the only way. We’re pretty used to calling this a WebSocket.

There’s another way to create these persistent connections using another web standard called Server-Sent Events (SSE), which is something really implemented in Oak.

SSE is basically a connection that stays constantly open from the client to the server, essentially a WebSocket, but you can communicate over HTTP instead of sending messages directly over TCP. And you do this through an endpoint.

On the frontend, we create an EventSource with an endpoint:

const eventSource = new EventSource("/api/users/123/notification/subscribe")

On the server side, we need to have a handler for that route, which will create a data stream:

import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
const router = new Router();
router.get('/api/users/:id/notification/subscribe', async (ctx) => {
const target = ctx.sendEvents()
const events = kv.watch(['users', ctx.params.get('id'), 'notifications'])
for await (const {value} of events) {
target.dispatchMessage({ notification: value })
}
})
app.use(router.routes())
await app.listen({ port: 8080 })

Whenever we have a change in our notifications array, we send it to the frontend and we can update our client.

Of course, this is a simple example, but it shows what we can do with this API.


Time for FTS!#

If you liked this article, I also have a complete TypeScript course called TypeScript Training!

I invite you to take a look there if you want to learn more about TypeScript with me and our amazing community with hundreds of students!