Host a Node.js Discord bot

3 min read07 November 2026

A Discord bot is not a website: it opens a persistent connection to the Discord gateway and needs no public HTTP port. On app hosting it must stay alive, reconnect after a network drop and keep its token out of the code. Here is a minimal setup and the details that separate a bot running for an hour from one running for weeks.

Prepare the project

Pick a recent Node.js runtime from those offered (22 LTS is a good balance). The project needs at least package.json, index.js and the dependencies installed by the platform.

Bash
npm install discord.js
JavaScript
const { Client, GatewayIntentBits } = require('discord.js');

const client = new Client({
  intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]
});

client.once('ready', (c) => console.log(`logged in as ${c.user.tag}`));

client.on('messageCreate', async (message) => {
  if (message.author.bot) return;
  if (message.content === '!ping') await message.reply('pong');
});

client.login(process.env.DISCORD_TOKEN);

client.login blocks the process and maintains the connection. No listen is needed. Create the token in the Discord developer portal and put it in the panel environment variables, never in index.js.

Intents and commands

Intents declare what the bot receives. Request the minimum: Guilds is enough for slash commands. MessageContent is privileged: enable it in the developer portal, otherwise Discord refuses the connection with Used disallowed intents.

For slash commands, register once, not on every start. A separate script or a REGISTER_COMMANDS=true variable that you later disable avoids duplicates and unnecessary API calls.

Memory and stability

discord.js caches guilds, channels and members. On a large server these caches quickly consume the plan's memory.

  • Do not enable GuildMembers unless needed.
  • Avoid walking and storing every member at startup.
  • Watch Map and array structures that grow without bound.
  • Do not leave an unreferenced setInterval if you recreate it on every event.

The library handles reconnection, but an uncaught exception in an event handler can bring the process down. Add an error listener and log without exiting abruptly. Rate limits are handled by the internal queue: avoid loops that send messages in bursts.

Token security

The token grants full control of the bot. If it leaks, reset it immediately in the developer portal: the old one is invalidated. Also check Git history if it was committed; removing it from the last commit is not enough. Grant only the permissions the bot needs and validate sensitive actions in code rather than trusting command parameters.

Check

The console shows logged in as ..., the bot appears online, a command replies and memory stays stable after thirty minutes. A reconnect loop usually means an invalid token or a refused intent, not a network issue.

Advertisement

Was this article helpful?

Read next