Opbeat is joining forces with Elastic – Learn more about Elastic APM

Freeze your requirements

Opbeat is built in Django and we use pip with a requirements.txt file to make sure we keep track of our dependencies. This is a pretty standard way to do it and it works very well, considering it is such a simple mechanism.

We use Fabric to deploy our code to production. Using pip, installing dependencies as part of deploying is dead easy:

def update_from_requirements():
    with prefix(env.activate_env):
        run("pip install -r requirements.txt")

(env.active_env is the path to the “activate” binary in our virtualenv)

When using this pattern, it is very important that nail each requirement to a version to avoid breaking you app when a module author changes things around. Doing so with packages installed from the Python Package Index is easy. To nail Django to 1.4.0 you can do:


Most modules are API stable between patch versions (the last of the three digit version numbers, if the author is using semantic versioning), so you can actually go a little futher to make sure you get patches for, for example, the Django 1.4.x versions:


However, I often find that there is a newer version of certain modules in their git repository. Luckily, you can add a module from any git repository directly in your requirement.txt file. Here is an example using the django-social-auth module:

-e git+https://github.com/omab/django-social-auth.git@egg=django-social-auth

As always when you use a requirements.txt file, you should make sure requirement specifications are locked to a specific version. I try to make sure we do that at Opbeat, however, recently we heard from some of our beta users that they were having trouble logging into Opbeat. I quickly checked Opbeat (yes, we eat our own dogfood) to see which changes were deployed recently. It turns out we had not locked the django-social-auth module to a git commit, so it was automatically updated by our deployment script, to the HEAD of the repository. As you can see below, Opbeat enables us to track exactly what was deployed:

I reverted to the previous version of the module and thing started to going back to normal immediately. In addition to being able to find out what was wrong, I was also able to tell exactly when things started to go wrong because of this.

You can specify a commit hash, tag or branch directly in the requirement.txt file:

-e git+https://github.com/omab/django-social-auth.git<strong>@38ec4c</strong>#egg=django-social-auth

@nickbruun contributed to this post.

About the author
Ron Cohen is co-founder and CTO at Opbeat. A founding member of Django Copenhagen, Ron enjoys sharing his experiences with code and ops around the world.
You can follow him on Twitter or GitHub.