My recent switch to Next.js has been both fun and educational. However, it also brought its share of unexpected hurdles. One of these hurdles was zero-downtime deployments. Yes, I could build Docker images for every site and deploy those with effectively zero downtime, but I didn't want to go that route - at least not at the moment.
The basic workflow for updating a site when I started this process looked something like this:
- Connect to the server via SSH and navigate to the project directory.
- Run
git pullto pull the latest changes. - Run
yarn buildto generate an optimized production build. - Run
pm2 reload mysiteto reload the server.
While this works, it also results in a brief period of downtime while generating the build and reloading the server. Obviously, this isn't ideal, so I looked for ways to improve my workflow. While researching, the goal expanded from simply zero-downtime deployment to automatic deployment from git.
The closest solution I found to what I wanted was next-pm2-deploy, but I had
two issues with it. First, it was built for the Pages Router, and I'm using the
App Router. More importantly, there were a few aspects of the deployment script
that I didn't like. So, I did what any self-respecting developer would do, and
rewrote it my way. So what does it do?
- Zero downtime, the deploy script only enables the new commit once the installation and build are successfully completed.
- Responds to
your-site.com/api/deployendpoint. - Rate limited to prevent abuse.
- Checks for existing deployment operation to prevent running concurrent deployments.
- Optional deploy key header for basic security from GitLab or GitHub.
- Cancels deployment if the current commit matches the live commit.
- Cleans up older and failed deployments to keep disk use minimal.
Want to set up something similar? The end results of my rewrite are available on my GitLab!
