Once your bot is ready, deploy it to production for 24/7 uptime. This guide covers building, optimizing, and hosting your CommandKit bot.
Building for Production
CommandKit includes a build system that optimizes your bot for production.
Build your bot
Run the build command to compile your TypeScript and optimize your code:This creates a dist/ directory with your compiled code. Test the build
Start your bot in production mode:Verify all commands and features work correctly. Prepare environment variables
Ensure all required environment variables are configured:DISCORD_TOKEN=your_production_bot_token
DISCORD_CLIENT_ID=your_bot_client_id
NODE_ENV=production
# Optional: Database and other services
DATABASE_URL=your_production_database_url
REDIS_URL=your_redis_url
Never commit .env files or expose your bot token. Use environment variables or secret management services.
Package.json Scripts
Ensure your package.json has these scripts:
{
"scripts": {
"dev": "commandkit dev",
"build": "commandkit build",
"start": "commandkit start"
}
}
dev - Development mode with hot reload
build - Compile TypeScript and optimize for production
start - Run the production build
Hosting Options
Railway
Railway provides simple deployment with GitHub integration.
Create Railway account
Sign up at railway.app and connect your GitHub account. Create new project
Click New Project → Deploy from GitHub repo → Select your bot repository.
Add environment variables
In your project settings, add:
DISCORD_TOKEN
DISCORD_CLIENT_ID
- Any other required variables
Configure start command
Railway auto-detects Node.js projects. Ensure your package.json has the start script:{
"scripts": {
"start": "commandkit start"
}
}
Deploy
Railway automatically builds and deploys on every push to your main branch.
Heroku
Heroku is a popular platform for hosting bots.
Login and create app
heroku login
heroku create your-bot-name
Add buildpack
heroku buildpacks:set heroku/nodejs
Set environment variables
heroku config:set DISCORD_TOKEN=your_token
heroku config:set DISCORD_CLIENT_ID=your_client_id
Deploy
git add .
git commit -m "Deploy to Heroku"
git push heroku main
DigitalOcean
Deploy on a VPS for full control.
Install Node.js
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt-get install -y nodejs
Clone repository
git clone https://github.com/yourusername/your-bot.git
cd your-bot
npm install
Create .env file
Add your environment variables:DISCORD_TOKEN=your_token
DISCORD_CLIENT_ID=your_client_id
Save with Ctrl+X, then Y, then Enter. Build and start
npm run build
npm run start
Use PM2 for process management
Install PM2 to keep your bot running:npm install -g pm2
pm2 start npm --name "discord-bot" -- run start
pm2 startup
pm2 save
PM2 automatically restarts your bot if it crashes and starts on server reboot.
Docker
Containerize your bot for consistent deployment.
Create Dockerfile
FROM node:24-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
CMD ["npm", "run", "start"]
Create .dockerignore
node_modules
dist
.env
.git
.gitignore
Build image
docker build -t discord-bot .
Run container
docker run -d \
--name discord-bot \
--env-file .env \
--restart unless-stopped \
discord-bot
Process Management
Using PM2
PM2 is a production process manager for Node.js applications.
# Install PM2 globally
npm install -g pm2
# Start your bot
pm2 start npm --name "discord-bot" -- run start
# View logs
pm2 logs discord-bot
# Restart bot
pm2 restart discord-bot
# Stop bot
pm2 stop discord-bot
# Auto-start on system boot
pm2 startup
pm2 save
PM2 Ecosystem File
Create advanced PM2 configurations:
module.exports = {
apps: [{
name: 'discord-bot',
script: 'npm',
args: 'run start',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: 'production',
},
error_file: './logs/err.log',
out_file: './logs/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
}],
};
Start with:
pm2 start ecosystem.config.js
Environment Variables
Required Variables
# Required
DISCORD_TOKEN=your_bot_token
DISCORD_CLIENT_ID=your_client_id
# Optional but recommended
NODE_ENV=production
Managing Secrets
Railway
Heroku
Docker
VPS
Add variables in project settings → Variables
heroku config:set DISCORD_TOKEN=your_token
Use --env-file .env or Docker secrets
Use .env file or export in shell profile
Logging and Monitoring
CommandKit Logger
Use the built-in logger for consistent logging:
import { Logger } from 'commandkit/logger';
Logger.info('Bot starting...');
Logger.warn('This is a warning');
Logger.error('An error occurred', error);
Log Files with PM2
PM2 automatically manages log files:
# View live logs
pm2 logs discord-bot
# View only errors
pm2 logs discord-bot --err
# Clear logs
pm2 flush
External Monitoring
Consider using monitoring services:
- Sentry - Error tracking and performance monitoring
- Datadog - Comprehensive monitoring and analytics
- UptimeRobot - Uptime monitoring
Database Considerations
If your bot uses a database:
Use production database
Don’t use your development database in production. Set up a separate production database:DATABASE_URL=postgresql://user:password@host:5432/production_db
Run migrations
If using Prisma or similar:npx prisma migrate deploy
Enable connection pooling
Use connection pooling for better performance:import { PrismaClient } from '@prisma/client';
export const prisma = new PrismaClient({
datasources: {
db: {
url: process.env.DATABASE_URL,
},
},
});
Backup regularly
Set up automated backups for your production database.
Enable Production Mode
This enables optimizations in Discord.js and CommandKit.
Reduce Memory Usage
import { Client, IntentsBitField } from 'discord.js';
const client = new Client({
intents: [
// Only enable intents you need
IntentsBitField.Flags.Guilds,
IntentsBitField.Flags.GuildMessages,
],
// Reduce cache size
makeCache: manager => {
if (manager.name === 'MessageManager') {
return manager.cache.sweep(m => m.author.id === client.user?.id);
}
return manager.cache;
},
});
Use Caching
Implement caching for frequently accessed data:
import { cache } from '@commandkit/cache';
// Cache guild settings
const settings = await cache('guild-settings', guildId, async () => {
return await database.fetchGuildSettings(guildId);
}, { ttl: 300 }); // 5 minutes
Continuous Deployment
GitHub Actions
Automate deployments with GitHub Actions:
.github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '24'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Railway
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
npm install -g @railway/cli
railway up
Health Checks
Implement health checks to ensure your bot is running:
src/app/events/clientReady/health-check.ts
import type { EventHandler } from 'commandkit';
import { Logger } from 'commandkit/logger';
export const once = true;
const handler: EventHandler<'clientReady'> = async (client) => {
// Periodic health check every 5 minutes
setInterval(() => {
Logger.info('Health check: Bot is running');
Logger.info(`Ping: ${client.ws.ping}ms`);
Logger.info(`Guilds: ${client.guilds.cache.size}`);
Logger.info(`Memory: ${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB`);
}, 5 * 60 * 1000);
};
export default handler;
Troubleshooting
Bot Not Starting
- Check logs for errors
- Verify environment variables are set
- Ensure bot token is valid
- Check Node.js version (requires Node.js 24+)
High Memory Usage
- Reduce Discord.js cache size
- Implement proper garbage collection
- Clear old data from memory
- Use database for long-term storage
Commands Not Updating
- Wait a few minutes for Discord to propagate changes
- Check if bot has proper permissions
- Verify
DISCORD_CLIENT_ID is correct
- Try removing and re-adding bot to server
Best Practices
- Use TypeScript: Better error detection and type safety
- Enable logging: Monitor your bot’s activity and errors
- Implement rate limiting: Prevent abuse and API overuse
- Handle errors gracefully: Never let errors crash your bot
- Use environment variables: Never hardcode sensitive data
- Set up automated backups: Protect your data
- Monitor performance: Track memory usage and response times
- Keep dependencies updated: Regular updates improve security and performance