How to Implement Caching in Sinatra/Ruby Apps

Sinatra is a lightweight web framework for Ruby. It’s a DSL that you can easily learn to build web applications faster or create apis that can easily serve millions of requests per day, while using least amount of RAM and CPU cycles (as compare to Ruby on Rails or other ruby frameworks). In this article, you will learn how to further optimise a Sinatra app by adding a simple in-memory caching system.

Ruby is my favourite language and I prefer Sinatra for most of my web projects, except when I’m creating something complex and going with the sensible default of Rails seems like a better choice. Recently, one of my website (sinatra based) was loading slow due to lots of database calls and implementing a caching system was the easiest thing to do to speed up the website. I used memcached because of its simplicity.

What is Memcached ?

Memcached is a high performance in-memory key value caching system. All the data is stored in memory (RAM) and it provides a very fast lookup via their keys. I just wanted to save expensive database calls, memcached is very efficient at this. Persistence was not required otherwise I would have selected redis.

Setting up Memcached on Ubuntu

Install it via your package manager or terminal.

sudo apt-get install memcached

Then you will also need a memcached client for ruby. I used the Dalli Gem. Add this to Gemfile and install it via bundler.

Here is a simple caching strategy I used for a blog. You could use this as starting point and customise it for your need.

Although default memcached config would serve you well but If you want to tweak few things for memcached, look at the configuration file at /etc/memcached.conf. To check the live status (total cached objects, ram consumed, hits, misses etc) use this command :

watch "echo stats | nc 127.0.0.1 11211"

When you’re working with caching, testing whether it works or not, flushing the cached objects is required sometimes. Here is that handy command to flush all the key-values from the memory :

echo 'flush_all' | nc localhost 11211

You could also pass options block to Dalli instance for setting an expiry timeline for stored objects.

>> options = { :namespace => blog, :expires_in => 10.day, :compress => true }
>> Dalli::Client.new('localhost:11211', options)

By implementing a simple caching using memcached saved me lots of expensive database calls, cpu power, and resulted in faster experience for the users as well. That’s win-win for everyone! (users, servers, developers ). Cache it if you can!

Relevant Links and References :

Leave a comment

Your email address will not be published. Required fields are marked *