Zelfs een goed geschreven bot kan om 3 uur 's nachts stilletjes sterven; daarom draait discord bot uptime minder om code en meer om operationele discipline. Het probleem is zelden dat de bot "slecht" is — het is dat niemand merkt dat hij crasht en dat er geen mechanisme is om hem weer op te starten. In deze gids stellen we stap voor stap in hoe je detecteert waaróm een bot uitvalt, hoe je hem zichzelf laat herstellen met pm2, en hoe je hem van buitenaf bewaakt met een eenvoudige healthcheck.
Waarom crashen bots?
Ken eerst je vijand. De overgrote meerderheid van de Discord-bots stopt om een handvol terugkerende redenen:
- Niet-afgevangen fouten: een exception die binnen een event handler wordt gegooid en niet in een
try/catchzit, haalt het hele Node.js-proces onderuit. - Ingeslikte promise-rejections: een promise zonder
awaitof.catch()laat het proces crashen op moderne Node-versies. - WebSocket-verbroken: netwerkhaperingen of herstarts aan Discords kant breken de verbinding; discord.js verbindt meestal vanzelf opnieuw, maar blijft soms hangen in een
disconnect-toestand. - Geheugenlekken: een steeds groeiende cache of niet-opgeruimde
setInterval's laten het proces binnen enkele uren met OOM (Out Of Memory) afsluiten. - Rate limits en ongeldige tokens: als de token gereset wordt of slechte code een vloed aan 429's veroorzaakt, wordt de gateway-verbinding geweigerd.
Als je naar deze lijst kijkt, wordt de oplossing duidelijk: maak fouten zichtbaar, zet een waakhond voor het proces, en meet van buitenaf of de bot echt "leeft".
Stap 1: stop met fouten inslikken
De eerste verdedigingslinie is de code zelf. Zelfs als de bot crasht, moet hij loggen waarom hij crashte, anders blijf je dezelfde fout eeuwig herhalen onder herstarts. Voeg listeners toe aan de discord.js-client en aan de globale procesgebeurtenissen:
client.on('error', (err) => console.error('[client error]', err));
client.on('shardError', (err) => console.error('[shard error]', err));
process.on('unhandledRejection', (reason) => {
console.error('[unhandledRejection]', reason);
});
process.on('uncaughtException', (err) => {
console.error('[uncaughtException]', err);
process.exit(1); // bewust afsluiten; laat pm2 herstarten
});
Hier zit een belangrijke ontwerpkeuze in: wanneer uncaughtException afgaat, beëindigen we het proces met opzet. Het proces in leven proberen te houden na een onbekende fout betekent doorgaan in een half-kapotte toestand. De schone aanpak is: loggen en afsluiten, en het herstel overlaten aan een procesmanager.
Stap 2: automatische herstarts met pm2
pm2 is een procesmanager die Node-apps op de achtergrond draait, ze automatisch herstart wanneer ze crashen, en hun logs verzamelt. Installeer hem globaal op je VPS:
npm install -g pm2
Je kunt de bot direct starten, maar de configuratie in een ecosystem.config.js-bestand bewaren is veel netter:
module.exports = {
apps: [{
name: 'discord-bot',
script: './index.js',
instances: 1,
autorestart: true,
max_memory_restart: '300M',
restart_delay: 5000,
max_restarts: 10,
min_uptime: '10s',
env: { NODE_ENV: 'production' }
}]
};
De velden die ertoe doen:
- autorestart: wanneer het proces afsluit, herstart pm2 het.
- max_memory_restart: herstart de bot proactief als het geheugen boven 300 MB komt — een verzekering tegen lekken.
- restart_delay: wacht 5 seconden voor de herstart, zodat een permanente fout zoals een ongeldige token geen eindeloze lus maakt die de CPU vastpint.
- min_uptime + max_restarts: als de bot 10 keer crasht zonder 10 seconden te blijven draaien, markeert pm2 hem als "errored" en stopt; dit voorkomt dat je een echt probleem verbergt onder eindeloze herstarts.
Om hem te starten en na een serverherstart weer omhoog te laten komen:
pm2 start ecosystem.config.js
pm2 save
pm2 startup # voer het getoonde commando uit
Gebruik pm2 logs discord-bot en pm2 status om logs en status te volgen.
Stap 3: een healthcheck-endpoint
pm2 beantwoordt de vraag "draait het proces?", maar kan de toestand "proces draait maar de Discord-gateway is weggevallen" niet betrappen. Om te verifiëren dat de bot echt leeft, voeg je een kleine HTTP-healthcheck toe. De ingebouwde http-module volstaat:
const http = require('http');
http.createServer((req, res) => {
// client.ws.status === 0 -> READY
const healthy = client.isReady() && client.ws.status === 0;
res.writeHead(healthy ? 200 : 503, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
status: healthy ? 'ok' : 'degraded',
ping: client.ws.ping,
uptime: process.uptime()
}));
}).listen(3001);
Nu toont curl http://localhost:3001 de gateway-status en ping van de bot. Het is cruciaal om dit endpoint te koppelen aan of de gateway echt READY is, en niet alleen aan process.uptime() — anders houd je een "levende dode" bot voor een gezonde bot.
Stap 4: externe monitoring en meldingen
De laatste schakel is op de hoogte worden gebracht wanneer er iets misgaat. Koppel het healthcheck-endpoint aan een gratis monitoringdienst (UptimeRobot, Better Stack of je eigen cron), zodat je bij een 503 of geen antwoord een e-mail/Discord-webhook-melding krijgt. Een eenvoudige zelf-monitoring-aanpak werkt ook:
setInterval(() => {
if (!client.isReady()) {
console.error('[health] bot niet READY, afsluiten');
process.exit(1); // laat pm2 schoon herstarten
}
}, 60_000);
Als de gateway stilletjes vastloopt, laat deze lus het proces bewust vallen zodat pm2 een schone herverbinding kan maken. Meestal is het beter om de eigen herverbindingslogica van discord.js af te wachten, maar voor "zombie"-toestanden is dit laatste redmiddel veilig.
Veelgestelde vragen
Kan ik mijn bot 24/7 draaien op gratis hosting (zoals Replit)?
De meeste gratis lagen zetten het proces in slaapstand als er geen verkeer is, dus de betrouwbaarste weg naar echte 24/7-uptime is een kleine VPS. Keep-alive-ping-trucjes zijn fragiel en schenden de gebruiksvoorwaarden van veel platforms. Voor één bot is een VPS van een paar euro per maand plus pm2 veel betrouwbaarder.
Moet ik systemd of Docker gebruiken in plaats van pm2?
Alle drie zijn geldig. systemd zit ingebouwd in Linux en biedt herstarts op serviceniveau; Docker doet hetzelfde met een restart: unless-stopped-policy. Wat pm2 aantrekkelijk maakt, is dat logverzameling, geheugengebaseerde herstarts en ergonomie zoals pm2 status in één tool zitten. Gebruik je al Docker, dan is de restart-policy van de container meestal genoeg.
Hoe stop ik een herstartlus die maar blijft crashen?
min_uptime en max_restarts bestaan precies hiervoor: crasht de bot te vaak in een korte periode, dan geeft pm2 het op. Gebruik dan pm2 logs om de grondoorzaak te vinden (meestal een ongeldige token, een ontbrekende env-variabele of een harde fout in de code) en los het op.
Valt jouw bot nog steeds zonder duidelijke reden uit? Ik kan crashdetectie, pm2-configuratie en healthcheck-monitoring voor je opzetten; voor een veerkrachtige, zelfherstellende botinfrastructuur, neem contact met me op.