How to Build a Shortlink App with Ruby and Redis


In this tutorial, we'll be building a quick shortlink web app with Ruby, the Sinatra web framework, and the Redis database. By the conclusion of this tutorial, you'll end up with a dead simple, high performance shortlink webapp that's super easy to scale.

Step 1. Getting Started

To follow along with this tutorial, you'll need Ruby installed on your system (I'm using 1.9.2), as well as the sinatra and redis gems, and Redis.

If you don't already have Ruby installed on your system, then you should be able to install it relatively easily. OS X, Debian or CentOS users may need to compile a newer version of Ruby. It's a pretty straightforward process.

Refer here to learn about how to install Ruby, via RVM.

Now you'll need to install the required Ruby Gems. Gems are a convenient way of installing virtually any Ruby library available. Simply type the following in your terminal window to install the required gems:

	gem install sinatra redis

We'll also need to install and compile Redis. Don't worry, it's really small and only takes roughly 15 seconds to compile on my machine.

	tar zfx redis-2.0.4.tar.gz
	cd redis-2.0.4
	sudo make install
	cd ..

You can run the Redis server by typing redis-server into your terminal, and if you feel like playing around with Redis, give redis-cli a go.

Step 2. Building the App

One of the great things about Sinatra is how quick and easy it makes whipping up simple little apps - it's almost silly!

The code for the shortlink app itself won't be very long, so it should be really easy to understand. Don't worry if you don't understand it at first, I'll explain how it all works shortly.

Make a folder for your webapp - I've called mine redis-ruby-shortlink - and put the following files in it.


	require 'sinatra'
	require 'redis'

	redis =

	helpers do
	  include Rack::Utils
	  alias_method :h, :escape_html

	  def random_string(length)

	get '/' do
	  erb :index

	post '/' do
	  if params[:url] and not params[:url].empty?
	    @shortcode = random_string 5
	    redis.setnx "links:#{@shortcode}", params[:url]
	  erb :index

	get '/:shortcode' do
	  @url = redis.get "links:#{params[:shortcode]}"
	  redirect @url || '/'

That's it. Pretty simple, eh?

In that little Sinatra app above, I've done a few key things. In the first two lines, I'm bringing in the libraries we need - sinatra and redis. On line 4, I establish a connection to the Redis server, listening on localhost. The lines after this is where it all starts to get interesting!

In Sinatra, you can specify helpers that are executed every time one of your routes (those get and post parts) is run. We can put anything that we might need often in the helpers block. In my helpers block, I've aliased h to Rack's escape_html, and defined a method to generate a random alphanumeric string of a certain length.

Next up are the routes. The first route is rather simple. Whenever a client makes a GET request to /, it just renders the index.erb page (I've included the source to this further down.)

The next route is where the good stuff happens. First, we make sure that the user has actually typed a URL into the URL box. If so, we generate a random shortcode five characters long by calling the random_string method we defined before. Then, we tell Redis to setnx (Set if n exists), a key representing our shortcode to its URL. Redis is a really fast and simple key/value database, or a NoSQL database. These databases are designed for really heavy key/value lookup operations, and as they drop most of the complexity of SQL, they can do it much faster. The 'links:' part of the key isn't strictly required, but it's good practice to split your Redis keys into namespaces so if you decide later on to store more information in the same database, you don't have to worry about clashes. After all that, we render the same index.erb page as before. Notice how if the user doesn't enter anything, this route does the same thing as the previous route.

The final route is run when a client visits a shortlink. This route introduces what's called a URL parameter. For example, when a client visits '/foobar', the :shortcode part of the route matches 'foobar'. We can access URL parameters the same way as any other parameter - the params hash. We look up the shortcode in the Redis database. If there's no such key as what we are trying to access, Redis will return nil. The next line redirects to either the URL we grabbed out of Redis (if it exists), or redirects to the homepage if not.


index.erb is mostly boring markup, although it does have a few lines I'd like to point out. erb stands for embedded Ruby, and allows us to mix Ruby and HTML, like you would with PHP.

	<!DOCTYPE html>
		<title>Shortlink App</title>
		body {
			font-family:"Gill Sans", "Gill Sans MT", Sans-Serif;
		.container {
			margin:120px auto 0px auto;
		h1 {
			border-bottom:2px solid #ff4b33;
		form {
		input {
		#url {
		#submit {
		#submit:hover {
		.clear {
		.result {
			border-top:2px solid #ff4b33;
		.result a {
		<div class="container">
			<h1>shortlink app</h1>
			<form method="post">
				<input type="text" value="<%= h(params[:url]) %>" name="url" id="url" />
				<input type="submit" value="shorten" id="submit" />
			<div class="clear"></div>
			<% if @shortcode %>
			<div class="result">
				Your shortened URL is:
				<a href="<%= @shortcode %>"><%= @shortcode %></a>
			<% end %>

One difference between erb and PHP that you may have already noticed (apart from the different languages) is that, where PHP uses <? and <?=, erb uses <% and <?=. The only interesting things about index.erb is the if block that only renders the part of the page that shows the shortlink if the @shortcode variable is defined. This lets us use the same view for everything. Another point of note is that we've made sure to HTML escape params[:url], so that we don't fall victim to an XSS attack. Other than those points, it's essentially a stock standard webpage.

Step 3. Scaling Up

One thing I briefly mentioned in this tutorial's introduction is how easily we can scale, thanks to Redis. Whereas scaling out to multiple SQL databases is a complicated affair, scaling Redis is actually quite trivial. This is a direct result of Redis' simplicity. If you need to scale to multiple Redises, add the following to your Redis configuration:

	slaveof 6379

Once you have multiple slaves set up, it's a tiny little tweak to the Sinatra app above to make each Sinatra instance connect to a random Redis server (if you're at the stage where you need to scale Redis, I'm going to assume that you've already had to deploy multiple Sinatra instances. ;)


I hope this tutorial proved to be useful to you, whether you want to run your own shortlink service, or you're simply interesting in the latest cutting-edge technologies that are available to us web developers. I've covered some pretty neat software in this tutorial that's been incredibly useful to not just me, but thousands of other developers out there. Enjoy your tinkering!

Related Posts
  • Web Design
    Building the Merry Christmas Web App InterfaceXmas build 2 retina
    Today we're going to build the Merry Christmas Web App Interface; a Photoshop layout from an earlier tutorial by Tomas Laurinavicius.Read More…
  • Code
    Authentication With Laravel 4Laravel 4 auth retina preview
    Authentication is required for virtually any type of web application. In this tutorial, I'd like to show you how you can go about creating a small authentication application using Laravel 4. We'll start from the very beginning by creating our Laravel app using composer, creating the database, loading in the Twitter Bootstrap, creating a main layout, registering users, logging in and out, and protecting routes using filters. We've got a lot of code to cover, so let's get started!Read More…
  • Code
    5 Reasons Why New Relic Is a Developer's Best FriendGetting started new relic retina preview2
    Once you start digging around New Relic you begin to realise just how many interesting features the service has to help monitor the performance and health of your application. It was truly difficult to pick just five things to talk about, so rather than focusing on the obvious features let's look at some of the less hyped functionality that New Relic provides and how we can use it in interesting and sometimes unorthodox ways. When we left you last time, we had a basic 'Hello World' Rails application (called New Relic_rails1, living in ~/project/tmp/New Relic). We will continue using this app, extend it and see if we can use it to demonstrate the features of New Relic that we'll be looking at.Read More…
  • Code
    JavaScript & AJAX
    Combining Laravel 4 and BackboneLaravel plus backbone 400
    For this tutorial, we're going to be building a single page app using Laravel 4 and Backbone.js. Both frameworks make it very easy to use a different templating engine other than their respective default, so we're going to use Mustache, which is an engine that is common to both. By using the same templating language on both sides of our application, we'll be able to share our views betweem them, saving us from having to repeat our work multiple times.Read More…
  • Code
    Building Ribbit in RailsRibbit rails
    Welcome to the next installment in our Twitter clone series! In this tutorial, we'll build Ribbit from scratch, not using PHP, but with Ruby on Rails. Let's get started!Read More…
  • Code
    JavaScript & AJAX
    Building Single Page Web Apps with Sinatra: Part 1Sinatra logo
    Have you ever wanted to learn how to build a single page app with Sinatra and Knockout.js? Well, today is the day you learn! In this first section of a two-part series, we'll review the process fo building a single page to-do application where users can view their tasks, sort them, mark them as complete, delete them, search through them, and add new tasks.Read More…