Skip to content

Development notes

Chukwuemezie Aneke edited this page Sep 13, 2022 · 1 revision

Design decisions and reasoning

At first to prototype I used disk serialization to persist the app's data to a file on disk. I wanted to check the robustness of disk serialization so I wrote a bash script to make 10 parallel requests to the server. These parallel requests caused a race condition which corrupted the json file that stored the url mappings.

The bash script proved that using a json file for data persistence is a bad idea so I used redis for data persistance. I considered other options for data persistence such as AWS S3, a full on database like mysql or postgresql, sqlite, or boltdb which is a go package for key-value data persistence. I ruled out a relational database like mysql because the app will be mostly fetching data and since the data is a simple key-value structure there's no need for more complex database operations like filtering, joining etc. My shortlist was narrowed down to boltdb and redis (with persistence). In the end I chose redis because I expect the app to be read heavy (a lot of requests to the short URL, which retrieves it from the database and redirects to the long URL) and it can potentially be write heavy too if a lot of URLs need to be shortened. Therefore redis is the better data persistence solution because it can do very high reads and writes, where as boltdb can do a high number of reads but average writes.

I decided to use docker and docker compose because I wanted the service to be portable and be able to run on any machine. I also wanted to reassure those who have security concerns about downloading a program from the internet, that because the service runs in docker containers, the program cannot see their system. Another reason for choosing docker is that I didn't want the user to manage the installation of dependencies on their system, for example when running the service in containers, the user doesn't have to install redis. Out of the box redis persists data in snapshots at intervals, without running the app using docker, the user would have to configure the redis.conf file to enable appendonly mode. The user doesn't have to remember how to install or run redis, they just use it.

I wanted to make deployment easy for the user, with just one command docker compose up the user can deploy a redis instance and the app instance, instead of having to start the redis-server and then start the app. Additional benefits of using docker is that the redis database is not shared between projects, so there will be no random exceptions because another project left some unwanted data in the database. Packaging the app and its dependencies (redis) also guarantees that anyone who downloads this project runs the same redis version as me, as my project expects.

I used JSON for the request datatype not just because it is the standard data transfer format between client and server but also because the input data (i.e. the long URL) could be coming from a service with no human interaction, such as an SQS queue or S3 bucket so it makes sense for the api to expect JSON input.

Clone this wiki locally