Implementing Zero-Downtime CI/CD for Node.js Apps on AWS EC2
Guide to Zero-Interruptions Deployment for Node.js on AWS EC2

Deploying code sounds easy — until you’re doing it multiple times a day while keeping your production server stable.
Our Node.js backend powers critical features, so even a broken build or 2–3 minutes of downtime wasn’t acceptable. As our team grew, deployment became risky:
Manual SSH deployments were slow
Missed steps caused crashes
Different machines had different Node versions
Rollbacks were painful
Hotfixes slowed down because the pipeline wasn’t automated
We needed a bulletproof CI/CD pipeline.
Below is the journey of how we moved from a patchy deployment process to a fully automated CI/CD setup using GitHub Actions + AWS EC2 + PM2.
The Problem
1 — Manual Deployments Became a Bottleneck
Every update required logging into EC2, pulling code, installing dependencies, restarting PM2, and praying we didn’t break something.
During busy days, this became tedious — and errors slipped in.
2 — No Consistency Across Deployments
One laptop used Node 16, another had Node 18.
Some deployments skipped tests.
Some forgot npm install.
Some overwrote .env accidentally.
We were relying on luck, not process.
3 — Zero Rollback Support
If something broke:
We scrambled to revert to the previous commit
Re-deployed manually
Restarted PM2 again
Not fast, not reliable.
We needed automation.
Step 1 — Setting Up GitHub Actions for CI
We began by automating the basics:
Install Node
Install dependencies
Run tests
Prepare build artifacts
GitHub Actions became our “CI engine”.
Why GitHub Actions?
Close to the repository
Easy secrets management
Parallel jobs
Free for most usage
Very simple YAML-based workflows
This ensured every push was validated before deployment.
Step 2 — Automating Deployment to AWS EC2
Next, we automated deployment.
Instead of SSH-ing manually to EC2, GitHub Actions now:
Builds the backend
Uploads the updated code to EC2
Restarts PM2 automatically
Verifies that the server comes back online
We securely stored:
EC2 host
SSH user
Private key
Environment variables
in GitHub Secrets, eliminating credential sharing.
This alone removed 90% of deployment friction.
Step 3 — Introducing PM2 for Zero-Downtime Restarts
PM2 became our process manager.
It allowed:
App restarts without downtime
Crash auto-recovery
CPU utilization monitoring
Log management
Easy rollbacks using saved snapshots
Whenever a deployment happened:
pm2 restart node-app
The app restarted instantly while keeping old connections alive.
Downtime: 0 seconds.
Step 4 — Handling Secure Environment Management
We moved all sensitive configuration from code into:
.envfile on EC2GitHub Secrets for CI
PM2 ecosystem config for runtime variables
This ensured:
No secrets in Git
Easy environment change without redeploy
Safer rollbacks
Step 5 — Improving Deployment Reliability
We refined the pipeline further:
Added health checks after deploy
To ensure the API booted correctly.
Added rollback capability
By keeping previous build folders.
Cleaned old build artifacts
To reduce EC2 disk usage over time.
Added monitoring
Using PM2 logs + CloudWatch.
Small improvements → Big stability gains.
Final Architecture Diagram
┌─────────────────────────┐
│ GitHub Actions │
│ (CI: Build & Test Code) │
└───────────┬─────────────┘
│
▼
┌────────────────────────────────────────────────┐
│ GitHub Actions Deployment Job │
│ 1️⃣ SCP/SSH to EC2 │
│ 2️⃣ Upload Build Files │
│ 3️⃣ Restart PM2 │
└───────────┬───────────────────────────┬────────┘
│ │
┌───────────▼────────────┐ ┌──────────▼─────────────┐
│ AWS EC2 Ubuntu │ │ GitHub Secrets │
│ Node.js + PM2 Runtime │ │ (SSH, Host, Env Keys) │
└───────────┬────────────┘ └─────────────────────────┘
│
┌───────────▼────────────┐
│ Node.js Application │
│ (Zero Downtime via PM2)│
└────────────────────────┘
Conclusion
Migrating to a CI/CD pipeline wasn’t just a tooling upgrade — it was an operational transformation.
With GitHub Actions + EC2 + PM2, we achieved:
Fully automated deployments
Zero downtime during restarts
Safe and secure environment handling
Consistent, reliable build process
Faster development cycles
No more late-night "quick fixes" breaking production
Today, pushing to main is all it takes for a clean, fast, safe deployment — every single time.

