Discord Bot CI/CD: Deploying Updates Without Bot Downtime in 2026

Published on

Manual bot deployments cause downtime and deployment anxiety. CI/CD automates the process so every git push deploys safely and predictably.

Discord bot hosting

Deploying your Discord bot should be one command (or zero commands, fully automatic). Manual deployments involving SSH, git pulls, and pm2 restarts while hoping nothing breaks are a recipe for eventual disaster. CI/CD eliminates the anxiety.

GitHub Actions: Automatic Deployment on Push

# .github/workflows/deploy.yml
name: Deploy Bot

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to VPS
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          script: |
            cd /home/bot/discord-bot
            git pull origin main
            npm ci --production
            pm2 reload discord-bot

Set secrets in GitHub repository Settings → Secrets → Actions:

  • VPS_HOST - Your server IP
  • VPS_USER - SSH username (e.g. bot)
  • VPS_SSH_KEY - Private SSH key content

Every push to main triggers automatic deployment. The pm2 reload ensures graceful restart (not abrupt kill).

Running Tests Before Deployment

Add a test step to the pipeline:

      - name: Run Tests
        run: npm test
        # If tests fail, the deploy step never runs

Even minimal tests (lint, type check) catch obvious errors before they reach production.

Rollback Strategy

When a deployment breaks the bot:

# On your VPS - rollback to previous version
cd /home/bot/discord-bot/
git revert HEAD --no-edit
git push origin main  # CI/CD deploys the revert

# Or manually:
git checkout HEAD~1 -- src/
npm ci && pm2 reload discord-bot

Maintain a staging branch that deploys to a test bot (different token, same code) before merging to main. Deploy staging, verify in test server, then merge to main for production deployment.

Zero-Downtime Slash Command Updates

Discord slash commands are registered via API, not loaded from files. Register commands in a separate step before the bot restarts:

// deploy-commands.js (run before starting bot)
const rest = new REST().setToken(process.env.DISCORD_TOKEN);
await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands });
console.log('Commands registered');

In the CI script, run node deploy-commands.js before pm2 reload to ensure commands are updated before the bot restarts.

Deploy your Discord bot with confidence on Space-Node