Building Subscription Application with Cloudflare Worker KVs
Tags: javascript, node, tutorial, programming
Published: 2023-01-23 12:23:22

Cloudflare workers is a service that lets us to deploy to the Cloudflare network distributed around 200 cities around the world. With this we are using the edge functions which servers us very low latency and is near to us geographically distributed.

Among many of the services provided by Cloudflare we are focusing on Workers Key Value(KV) Store. We will bring here official KV definition from Cloudflare docs



> Workers KV is a global, low-latency, key-value data store. It stores data in a small number of centralized data centers, then caches that data in Cloudflare’s data centers after access. KV supports exceptionally high read volumes with low latency, making it possible to build highly dynamic APIs and websites that respond as quickly as a cached static file would. While reads are periodically revalidated in the background, requests which are not in cache and need to hit the centralized back end can see high latencies.

[Official docs](https://developers.cloudflare.com/workers/runtime-apis/kv/)

## What will we build

We will build a simple API where we will be interacting with the KV to get all KV, get a one KV, put new KV storage.

**We will build a mini subscription application which lets us store the email, status(free/premium), id in a KV Store. This will help us to know which users belongs to the free plan or premium plan.**

We can start by installing Wrangler if you dont have it in your local machine. Its a CLI with helps us to create workers project locally.

```shell
npm install -g wrangler
```

After installation we are ok to create our worker project. Where we will be using a Javascript to write all the logic currently. But you can use the official templates provided with many launguage as your choice.

```shell
wrangler init project-name
```

We can now start by creating a new folder and name it utils. Here we can add any functionalities which can help us interact with the [KV methods](https://developers.cloudflare.com/workers/runtime-apis/kv/#methods).

## Installing dependencies

We will use a bare minimum dependencies as possible. Lets add two packages with command below

```shell
npm i itty-router nanoid
```

_itty-router_ is the routing library which we will use.
_nanoid_ is the library we will use for generating unique ids.


## Generating new KV Namespace

To get started with KV Storage you need a namespace to be generated. Below are the commands you will need.

```
npx wrangler kv:namespace create "SUBSCRIPTIONS"
 
npx wrangler kv:namespace create "SUBSCRIPTIONS" --preview 
```

The--preview option informs Wrangler it’s for preview only, which is specifically for development mode.

You might need to create a cloudflare account to generate your workers id. You can get it from the[dashboard](https://dash.cloudflare.com/).

Below is the example of updated wrangler.toml file with the information needed

```javascript
name = "kv-worker-demo"
type = "webpack"
main = "src/index.js"
account_id = "**********"
workers_dev = true
compatibility_date = "2023-01-21"
webpack_config = "webpack.config.js"
kv_namespaces = [
	{ binding = "SUBSCRIPTIONS", id = "*********", preview_id = "*********" }
]
```



## Creating routes


```javascript
import { Router } from "itty-router";

const router = Router();

router.get("/api/subscriptions", async (req) => {
  return new Response("Workers running...", { status: 200 });
});

router.get("*", () => new Response("Not found", { status: 404 }));

export const handleRequest = (request) => router.handle(request);
```

We will make the use of router from our itty-router library. and create a get request route for two basic endpoint where we have a general route with a astrix and /api/subscribers to interact with our workers listening.





## Get all subscribers 

To get all the records of the subscribers we could make the use of the namespace we created and return empty if we dont find one.


```javascript
import { KV_KEY_ID } from '../handler'

export const getAllSubscriptions = async () => {
  let subscriptions = await SUBSCRIPTIONS.get(KV_KEY_ID)
  if (subscriptions === null) {
    return []
  }
  return JSON.parse(subscriptions)
}
```


```javascript
export const KV_KEY_ID = 'subs'

router.get('/api/subscriptions', async req => {
  const allSubs = await getAllSubscriptions()
  return new Response(JSON.stringify(allSubs))
})
```


## Creating new subscriber 

To create a new subscriber we need a POST request. This would first take in a request body and calls a function addSubscriptions taking in the content as a parameter. 

```javascript
router.post('/api/subscriptions', async req => {
  let content = await req?.json?.()
  if (content == undefined) {
    return new Response('Please provide a request body.')
  }
  content['id'] = nanoid()
  let subs = await addSubscriptions(content)
  return new Response(JSON.stringify(subs))
})

```

We need to create a addSubscriptions function which will make a call to our previous function and pushes a new item into that array. 

Lastly we need to make a PUT request to our worker to notify the change with a .put() method available to us.


```javascript
export const addSubscriptions = async (sub) => {
  let subscription = await getAllSubscriptions()
  subscription.push(sub)
  await updateSubscriptions(subscription)
  return sub
}

export const updateSubscriptions = async (sub) => {
  await SUBSCRIPTIONS.put(KV_KEY_ID, JSON.stringify(sub))
}
```


## Getting one subscriber

We can also get the request parameter and find the needed KV from our store. 

And finally return a stringified version of the id that is passed in to us from the request object.


```javascript
router.get('/api/subscriptions/:id', async req => {
  let allSubs = await getAllSubscriptions()
  let subID = allSubs.find(a => a['id'] == req.params?.id)
  if (!subID) {
    return new Response('This ID is not matched')
  }
  return new Response(JSON.stringify(subID))
})

```

This is how we can make the use of Cloudflare KV for our data storage solution makes it handy. We used a multiple, kv_namespaces accepts an array of objects. 

We could add still more functions where we could use the delete, listing only keys, Time to live(TTL), Expiring keys and many awesome features baked in. 

You can learn more from [here](https://developers.cloudflare.com/workers/runtime-apis/kv/#methods)


You can find the complete code repository [here](https://github.com/isNan909/cloudflare_kv_storage).

Happy coding!

## Reading references

[Workers KV](https://developers.cloudflare.com/workers/)
[How KV Works](https://developers.cloudflare.com/workers/learning/how-kv-works/)
[Durable Objects](https://developers.cloudflare.com/workers/learning/using-durable-objects/)
https://youtu.be/dei8fOR_Of8