There is a time, when we need to switch our apps into maintenance mode. Maybe it is because of some data processing stuff, maybe because of backups, deployment or whatever good reason you might have. To be honest it doesn’t matter why. What does matter, is how we should handle working users of our apps. Even if you use a zero downtime deployment using Puma (great article on howto here), sometimes you just need to shutdown your app for few minutes.

Of course all the downtimes should take place when there is the smallest amount of users online. In most cases it might be a good idea to switch application off in the middle of the night (or on Sunday, etc.), but this won’t solve our primary problem: what should we show users that are already online?

The worst scenario ever would be showing them nothing (for example by shutting down whole application server). Users probably will think, that something bad happened. Much better idea is to show users a maintenance page with some sort of information like “Temporary down for maintenance”. It would be even better, if such a page would automatically display when needed.

In order to obtain this, we need to do two things:

Configure our Nginx server block

Add an additional Capistrano task

503 configuration for your Nginx server block (virtual host)

Add this at the end of your server block configuration (before the last curly bracket). It will test if a maintenance.txt file exists in a tmp directory, and if so, it will serve a 503 error page. It is worth pointing out, that all the assets will be served normally (we ignore them):

Capistrano hookup

To automate turning maintenance page on and off, I use a set of simple Capistrano tasks, enclosed in a Nginx namespace:

namespace :nginx do
desc 'Switch current project into maintenance mode'
task :lock do
on primary :db do
within release_path do
execute :touch, 'tmp/maintenance.txt'
end
end
end
desc 'Turn off current project maintenance mode'
task :unlock do
on primary :db do
within release_path do
execute :rm, '-f tmp/maintenance.txt'
end
end
end
end

Usage example (in my deploy.rb):

namespace :deploy do
before :starting, 'nginx:lock'
# Some other tasks...
after :finished, 'nginx:unlock'
end