While working on CronMonit, I needed a way to be able to do deployments with zero-downtime and zero hanging requests.
CronMonit is a cron monitoring tool and it is able to monitor cron jobs by receiving pings (HTTP requests). A service like this can't have many downtimes or hanging requests because even just missing a few pings will cause issues for its users. Like a "cron job is down" email notification being sent even if the cron job is not really down. And because I do deployments frequently, having a way to do deployments with zero downtime and zero hanging requests is crucial.
This is the current tech stack of CronMonit:
- Rails 6
All of them are running on a single $5 DigitalOcean droplet (Ubuntu 18.04 LTS).
Luckily, it is very easy to a deployment with no downtime and no hanging requests on a rails app using puma web server. Puma has a feature called "phased restart" which kills puma workers one-by-one.
To use it, just spawn up at least 2 puma workers.
RAILS_ENV=production bundle exec puma -w 2
Then when you need to restart puma, use the phased restart feature:
bundle exec pumactl phased-restart
Here's an example scenario that explains the process:
- Do code changes on your local development environment
- Commit or merge the changes to master branch
- Push the changes on master branch to your central git repository (e.g, Github)
- SSH into your server
- cd into the directory of the git repository on your server
- Pull updates from master branch (e.g, git pull origin master)
- Then restart puma using phased restart
If you're using cron jobs or scheduled tasks, you can monitor them using CronMonit for free: https://cronmonit.app/
Here's a blog post on how it works: