Hot compatibility beyond databases

Feb 12 2012

Hot compatibility doesn't only apply to database migrations. Modern web applications can have a wide range of dependencies that without proper planning will break your deploy in subtle, unexpected ways.

Self dependency

The first dependency for every web application is itself: HTML pages with forms are likely going to get out of sync after a deploy - consider a user filling a form rendered from a certain version of your application, while the server that is going to receive his POST request is one version ahead.

The only safe approach to change the semantics of a form in use is to make sure that all changes are backwards compatible; if you're renaming a field, make sure your server understands both, for instance.

This obviously goes in hand with database migrations, at least when you're changing the form to reflect schema changes.

Caching

The identifier of any cached assets should be unique across different deploys. This comes for free with some caching frameworks (like the asset pipeline introduced in Rails 3.1), but if you're managing your own cache you need to consider this or your users will load the wrong JS/CSS when you deploy.

Internal APIs

Just go ahead and version every single API you write. From day one. Seriously. Avoid being hunted by the API gods.

Other databases

Migrating relational databases is a problem, but that doesn't mean NoSQL is the answer. Most alternatives will allow you to skip schema migrations, but not data - and when manipulating data you'll probably want to consider the same patterns that are applied to relational databases.

Pay attention to validations and constraints too - they might have moved from the database to your application layer, but still need careful planning to be introduced or modified in production. The solution, once again, is to make sure that any code being introduced is compatible to one that is already running.

Closing thoughts

What a pain in the ass.

I would never encourage this practice for a personal site, or in fact for any site with low traffic - but once you reach a certain size (or standard) this is just the only way to go.

The good news is that the overhead introduced by these techniques is surprisingly low, at least in my experience. At the Heroku API we're not doing destructive changes that often, and when we do, having an easy, streamlined workflow to deploy helps us get it out of the way quickly.