Prototyping fun with Flask and Redis.

I don't know about you, but I like prototypes. Maybe too much. I'd prototype myself if I could. But I find it increasingly hard to get small projects off the ground... compile ruby, update rubygems, something is broken, download node, compile node, npm grunt, write a list of dependencies, what was I trying to do again? Sounds familiar? There must be a better way! Well, there is.


A bit about Redis

Redis ( is an in-memory key-value cache and store. It can contain strings, hashes, lists, sets, order sets, and hyperlogslogs. It also has many extra components that can make an application really powerful: pub-sub, keys with limited time-to-live, master-slave data replication, and much more. Some things I really like about it is atomic operations, really handy where many clients interact with the same data, and powerful querying (ranking, counters) on keys. And since it runs in RAM its blazingly fast!

Sure, you say, SQL does all that and more. Sure, I say, but Redis is very light weight and really easy to use. Moreover, since I used it first it has only become more robust and powerful.

A bit about Flask

Flask is plain awesomeness. It's a micro-framework for Python that is really easy to setup and fun to use It is a WSGI framework with URL routing that is easy to understand and debug, allowing you to prototype web apps really easily, for example setting a route and response objects is as simple as:

def hello():
    return "Hello World!"

In comparison to other mega frameworks (Django) and smaller frameworks that try to re-invent the wheel (Bottle), Flask is a straightforward, no-bs framework. Plus, I have not had this much fun using a framework since I first used Sinatra many years ago.

Setting up things:

In Ubuntu/Debian:

sudo apt-get install python python-pip redis-server
pip install flask redis

Really? I'm done setting up? Yup.

A minimal Redis-Flask data-key store app with flexible routing

I want to create a single entry point that allows me to create a resource when issuing a PUT request. I want this resource to not serve (error) GET requests unless previously created. And I want resources to be cleared after a year.

First things first (routing). Turns out, flexible routing can be done quickly like this:

@app.route('/', defaults={'path': ''}, methods = ['PUT', 'GET'])
@app.route('/<path:path>', methods = ['PUT', 'GET'])
def home(path):
    return "Your path is: " + path

Sigh, refreshing. Now let's power up redis:

db = redis.Redis('localhost')

We will now write the prototype app, in one method, like a boss. Redis (through redis-py, which is what we are using has a powerful hash API that will suffice all our needs.

@app.route('/', defaults={'path': ''}, methods = ['PUT', 'GET'])
@app.route('/<path:path>', methods = ['PUT', 'GET'])
def home(path):

    if (request.method == 'PUT'):
        event = request.json
        db.hmset(path, event) #store dict in a hash
        return json.dumps(event), 201

    if not db.exists(path): #does the hash exist?
        return "Error: thing doesn't exist"

    event = db.hgetall(path) #get all the keys in the hash
    return json.dumps(event), 200

That works, but I want to now have it so that we don't have zombie keys on the hash (when the client stops updating a key or the schema of our event changes), and make it so that old keys are deleted from Redis after a year. No problemo:

@app.route('/', defaults={'path': ''}, methods = ['PUT', 'GET'])
@app.route('/<path:path>', methods = ['PUT', 'GET'])
def home(path):

    ttl = 31104000 #one year in seconds
    if (request.method == 'PUT'):
        event = request.json
        event['ttl'] = ttl
        db.delete(path) #remove old keys
        db.hmset(path, event)
        db.expire(path, ttl) #expire it after a year
        return json.dumps(event), 201

    if not db.exists(path):
        return "Error: thing doesn't exist"

    event = db.hgetall(path)
    event["ttl"] = db.ttl(path)
    return json.dumps(event), 200

We're done! Well, not quite. If you run this code you'll find out that if a client PUTS the object:


and later retrieves it, sometimes (depending on your implementation of redis-py and json) you might get:


This will cause many pains when parsing the javascript object in a client. So, we need to cast integers in our dictionary. We do this with some magic:

# A method to find out if a value is an integer, clunky but worky
def isInt(s):
        return True
    except ValueError:
        return False

event = {"hello":"world","answer to everything":"42"}
print dict((k,int(v) if isInt(v) else v) for k,v in event.iteritems())

My final app now looks like this:

And its unit tests. Coming from Rails I wrote these guys first, but forefront tests don't make good posts.

How's Redis porformance in all this? Running a bash script I found that for about 2,000 created "things" or hashes


Whoop whoop! Not bad.

Trying it out

By suggestion of itamarhaber (Thanks Itarmar for the Heroku button code and setup!) you can quickly deploy this example in Heroku through the repo ( And try it out at:

curl -H "Content-Type: application/json" -X PUT -d '{"value":123}'


And another instance (by itamarhaber):

curl -H "Content-Type: application/json" -X PUT -d '{"value":123}'


I hope this post was helpful in any way. If you enjoyed this post, need the code, or want to rant check it out on Github, no strings attached:

  • Itamar Haber

    Good stuff – the only thing missing is deploying this to a free Heroku dyno, slapping on a free Redis Cloud instance and putting the link to the prototype’s demo :)

    Will be included in the upcoming (#48) Redis Watch newsletter – Itamar.

  • Aditya Verma

    Cool, a basic Redis example. I was having doubts about using a flask extension or pure python Redis client. I think will go with pure python client now.