Running a Discord Bot on a VPS: Node.js vs. Python Setup Guide for 2026

Published on | Updated on

A Discord bot needs to be online 24/7 to be useful. Moving it from your local machine to a VPS is simpler than you think - here's the complete setup.

Written by Jochem, Infrastructure Engineer at Space-Node, 5-10 years experience in game server hosting, VPS infrastructure, and 24/7 streaming solutions. Read author bio →

A Discord bot that only runs when your computer is on is barely useful. Members test the bot at 3 AM and it doesn't respond. The solution: host it on a VPS and let it run 24/7. This guide covers both Node.js (discord.js) and Python (discord.py) setups.

Prerequisites

  • A Space-Node VPS (smallest plan works for most bots)
  • SSH access
  • Your bot code repository (GitHub, GitLab, or local zip)

Node.js Bot Deployment

# Install Node.js 20 LTS (Ubuntu)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install nodejs

# Clone your bot
git clone https://github.com/yourusername/your-discord-bot.git /home/bot/
cd /home/bot/

# Install dependencies
npm install

# Test run
node index.js

Python Bot Deployment

# Install Python 3.11+
sudo apt install python3 python3-pip python3-venv

# Create virtual environment
python3 -m venv /home/bot/venv
source /home/bot/venv/bin/activate

# Clone and install
git clone https://github.com/yourusername/your-discord-bot.git /home/bot/code
cd /home/bot/code
pip install -r requirements.txt

# Test run
python3 bot.py

Keeping the Bot Running with PM2

PM2 manages the process lifecycle:

# Install PM2
npm install -g pm2

# Start Node.js bot
pm2 start index.js --name my-discord-bot

# OR Python bot
pm2 start "python3 /home/bot/code/bot.py" --name my-discord-bot

# Save process list and enable on startup
pm2 save
pm2 startup  # Follow the output instruction

Managing Environment Variables Securely

Never put your Discord token in your source code. Use environment variables:

# Create .env file (NOT committed to git)
cat > /home/bot/.env << 'EOF'
DISCORD_TOKEN=your_token_here
DATABASE_URL=your_db_url_here
EOF

# Load in Node.js:
require('dotenv').config({ path: '/home/bot/.env' })
const token = process.env.DISCORD_TOKEN

# Load in Python:
from dotenv import load_dotenv
load_dotenv('/home/bot/.env')
token = os.getenv('DISCORD_TOKEN')

Updating Your Bot

cd /home/bot/code/
git pull origin main
pm2 restart my-discord-bot

Set up a GitHub webhook to automate this, or run it manually after each push.

Host your Discord bot 24/7 on Space-Node

When to pick Node.js vs Python for a Discord bot

DecisionNode.js (discord.js)Python (discord.py / py-cord)
Slash command ergonomicsexcellentexcellent
Voice supportgood (with @discordjs/voice + ffmpeg)good (with PyNaCl + ffmpeg)
Music bots at scaleLavalink + Java is the metasame Lavalink, less common
ML / pandas integrationpoorexcellent
Type safetyTypeScripttype hints
Hosting RAM at idle80-120 MB60-90 MB

discord.py was unmaintained for a while in 2021-2022; the active fork most people use today is py-cord (or the resurrected discord.py 2.x). Both are stable in 2026.

VPS sizing

Bots / usersvCPURAMDisk
1 bot, < 1k servers11 GB20 GB
1 bot, 1-10k servers22 GB40 GB
Multiple bots, shared host24 GB50 GB
Music bot with Lavalink2-44 GB30 GB

systemd unit for a Node bot

[Unit]
Description=My Discord Bot
After=network-online.target

[Service]
Type=simple
User=bot
WorkingDirectory=/home/bot/mybot
ExecStart=/usr/bin/node dist/index.js
Restart=always
RestartSec=5
EnvironmentFile=/etc/mybot.env
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Sharding threshold

Discord requires sharding once your bot is in 2500+ servers. Both libraries handle this; on Node, set shardCount: 'auto' in the Client constructor. You don't need to touch shards before that scale.

Things that surprise people

SurpriseReasonWhat to do
Bot intermittently misses messagesgateway intent not enabledenable intents in dev portal AND in code
"Disallowed intents" errorprivileged intents not whitelistedrequest approval (required at 100+ servers)
Token leaked, can't roll fasttoken in git historyuse BFG / filter-repo, then regenerate
Memory grows over weekscache.MessageManager unboundedconfigure cache sweepers

Cache sweeper example (discord.js)

const client = new Client({
  sweepers: {
    messages: { interval: 3600, lifetime: 1800 },
    users:    { interval: 3600, filter: () => u => u.bot && u.id !== client.user!.id },
  },
});

Without sweepers, message cache will hold every visible message forever and OOM the process eventually.

Jochem

About the Author

Jochem, Infrastructure Engineer at Space-Node, expert in game server hosting, VPS infrastructure, and 24/7 streaming solutions with 5-10 years experience.

Since 2023
500+ servers hosted
4.8/5 avg rating

I specialize in Minecraft, FiveM, Rust, and 24/7 streaming infrastructure, operating enterprise-grade AMD Ryzen 9 hardware in Netherlands datacenters.

View my full bio and credentials →

Keep Your Bot Online 24/7

Reliable Discord bot hosting powered by enterprise AMD Ryzen 9 hardware. Start free, upgrade anytime with guaranteed uptime.