Building Subscription Application with Cloudflare Worker KVs
ishan
Posted on January 23, 2023
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.
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.
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.
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.
Installing dependencies
We will use a bare minimum dependencies as possible. Lets add two packages with command below
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 thedashboard.
Below is the example of updated wrangler.toml file with the information needed
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
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.
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)
}
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.
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.
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.
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
You can find the complete code repository here.
Happy coding!
Reading references
Workers KV
How KV Works
Durable Objects
https://youtu.be/dei8fOR_Of8
Posted on January 23, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.