Little Link is a 6-hour project inspired by bit.ly, tinyurl.com, and similar sites. It takes a long URL and returns a compact version that, when accessed, will redirect the user to the desired long URL originally input.
The production website is available at https://www.litl.ink.
- Clone the repo and install dependencies with
yarn install
. - Install Redis and start a local redis server with
redis-server
. - Create a .env file in the root directory and add two values:
REDIS_URL=[your redis url]
ENVIRONMENT="DEVELOPMENT"
The default Redis URL is "redis://:6379"
- Start the server with
yarn start
. - Navigate to
http://localhost:8080
and enjoy the app.
If you would like to run tests, run yarn test
.
- Node, Express
- Redis
- HTML, CSS, Javascript, JQuery
- Jest, eslint
- Heroku
As our primary concern for this site is availability and speed, and as our querying needs are extremely simple
(literally get the value at a given key), our use case is perfect for a key-value store database. Every time
a URL is provided we create a hash and store mirrored pairs in the DB. {Hash: URL}
, and {URL: Hash}
.
The 32-bit hashes generated from the passed-in URLs are created from a combination of the URL and the timestamp at which they were added. In the event of a collision, the app waits 2 milliseconds and creates a new hash, and continues doing so until such time as an empty slot is found. Hashes expire after 7 days of non-use.
The 32-bit hash is a compromise between likelihood of collision and length. If I were to acquire ~30,000 hash values in my database, the odds of collision would be approximately 1/10. If I ever get in that range, I will be very happy at the success of my site, but I do not expect that to happen.
If a user attempts to add a URL that is already in the database, the DB simply returns the present hash and extends its lifespan for another 7 days.
As speed is of utmost importance and the front-end demands are extremely minimal, I opted to build a static HTML page for the front end and serve it from the Node server rather than building an independently deployable front end as I have with other projects. This makes the back-end resources more readily available to the front-end and trivializes CORS setup.
As I have deployed the app to Heroku I do not expect to be personally responsible for scaling. However, if I were, I have designed the app such that it would be extremely simple. It would be a matter of read replications of the database (made easier thanks to using a NoSQL DB) and replications of the controller layer behind a load balancer.
Thank you for checking out the repository. If you have questions, feel free to reach out at howard.reith@gmail.com.