URL Shortener built with Cloudflare Workers KV

URL Shortener

Cloudflare introduced a new service called Workers that I used to build a URL Shortener. Other cloud companies have something similar. Google has Cloud Functions and Amazon has Lambda. Since this “serverless” thing is starting to catch on I decided to build something as a way to learn more about it.

At first I built an image hosting site, as I usually do when learning about new technologies. I incorporated DigitalOcean’s Spaces for my storage. My Worker would check the URL, and if it began with the letter “x,” it would grab the file from the Object Storage. It would then store the file in the Cloudflare cache. Doing this meant I had unlimited storage, and unlimited bandwidth. I was pretty happy about how this turned out, but I knew it could never compete with other image hosting sites. Also, moderating it would be a pain in the ass.

I applied for the beta program for Cloudflare’s Worker Key-Value store. My request was approved before I had any idea about what I wanted to build. There some limitations to Workers KV, such as the key has to be less than 2kB and the value has to be less than 64kB. You get 20 namespaces, and you can have 1 billion keys per namespace.

URL Shortener

After some thinking I decided to build a URL Shortener because it seemed fairly straight-forward. It’s a great use case for a simple Key-Value store like the one I would be using. The Key is the short part of the URL and the Value is the long URL. As I did with the image hosting, I prefixed these routes with the letter “s”. When it encountered a short URL route, it would find the value in the KV store, and then return a 302 redirect.

Storing the URL Shortener data

At first, I had a form that would POST to the same URL, then queue a job to create the entry in the KV store. While this worked, and the queue helped the page load faster, there was still a delay before the short URL would work. So I ended up redoing it with React and having it post to a new route my Worker handled and immediately wrote it to the KV store. Excellent, so now the user experience is improved, but I wasn’t getting all the data I wanted.

I could have created another KV namespace to store the additional metadata about the shortened URL, but I wanted it more accessible to me. At first, I wrote some code to post the metadata to my origin server after it handled the creation of the KV creation. Again, this worked but wasn’t optimal. I didn’t want to be responsible for scaling my origin server to handle a large amount of traffic.

After Googling for awhile, I finally found a service I liked. The website restdb.io allows me to easily POST the metadata to an API endpoint, and they save the data. I’m not married to this solution, and it can easily be changed to another service. But for now, they have to manage scaling for my metadata.

Why a 302?

You may be wondering why I chose to use a 302 redirect instead of a 301. In the future of this web app I might allow users to change the destination URL of their short URL. Also, a 301 redirect seems too permanent for me, and I’m not ready for that level of commitment.


I created another namespace to keep track of very basic usage of each short URL. The key is the same as the one used by the short URL, but the value is the number of times it has been used. This value is returned in every response header when you use one of the short URLs. So, in essence, you can curl the URL to see how many hits it has received.


By engineering my URL shortener this way, my origin server doesn’t do much. Cloudflare grabs the HTML/CSS/JavaScript from my origin, and caches it for a month, or until I purge it. Then the react app talks directly to the Cloudflare Worker KV store. And the Cloudflare Worker KV store talks directly to the restdb.io instance.

This service is run on edge servers all around the world, so it is very fast, probably the fastest URL Shortener on the internet. I’m aware that is a bold statement, but I believe it to be true. The next time you need to shorten a URL, use mine, please. It’s called xsf since most URLs are excessively long.