What a bot needs, honestly
Very little. A Discord bot is mostly an idle websocket connection waiting for events.
- RAM is the real constraint, and 1 GB is enough for a typical bot in Python or Node. It stops being enough the moment you add music playback, image processing or a local database.
- CPU barely matters until you transcode audio. A music bot streaming to one voice channel is a different animal from a moderation bot — plan for that one specifically.
- Bandwidth is negligible for text, meaningful for voice. A music bot pulling audio and pushing it to a channel moves real traffic; the cheapest tiers include enough for a hobby bot and not enough for a busy one.
- Region should be near your users, not near you, though for a text bot the difference is invisible. For voice it is audible.
Step 1: Put it somewhere it can be restarted
Run the bot as a service, not as a command you typed. This is the single change that turns "it dies overnight" into "it came back in four seconds".
With systemd, a unit file is enough:
[Unit]
Description=discord bot
After=network-online.target
[Service]
WorkingDirectory=/opt/bot
ExecStart=/usr/bin/node index.js
EnvironmentFile=/opt/bot/.env
Restart=always
RestartSec=5
User=bot
[Install]
WantedBy=multi-user.targetThen enable it so it also survives a reboot, which is the failure everyone forgets until the host reboots the node:
sudo systemctl enable --now discord-bot
sudo journalctl -u discord-bot -fIf you prefer containers, restart: unless-stopped in a compose file does the same job and keeps dependencies out of the host.
Step 2: Keep the token off your machine and out of git
A leaked bot token is a stranger with your bot's permissions, and Discord's scanner will invalidate it the moment it appears in a public repository — which is the good outcome.
- Put the token in a
.envfile on the server, owned by the bot user, permissions600. - Add
.envto.gitignorebefore the first commit, not after the first leak. - If a token has ever touched a public repo, a screenshot or a chat message, regenerate it. There is no "probably fine".
Step 3: Plan for the crash you have not written yet
Restart-always handles the process dying. It does not handle the bot being alive and useless — logged in, connected, and silently failing every command because a dependency is down.
- Log to the journal or to a file, and read it after the first week. The bugs that matter are the ones you never see because nobody reports them.
- Watch memory. A bot that leaks slowly gets killed by the OOM killer at 4 a.m., and
Restart=alwayswill cheerfully restart it into the same wall. - If uptime genuinely matters, have the bot report a heartbeat somewhere and alert on silence rather than on errors.
What this actually costs
Ours, for reference, billed by the hour from a prepaid balance:
| Plan | vCPU / RAM / disk | Price |
|---|---|---|
| Micro | 1 / 1 GB / 25 GB | $10/mo |
| Starter | 1 / 2 GB / 50 GB | $18/mo |
| Standard | 2 / 4 GB / 80 GB | $34/mo |
Micro runs a text bot comfortably. Starter is the sane choice if the bot has a database or you expect to add features. Standard is where music bots start behaving.
One box can hold several bots — separate systemd units or separate containers, one server. That is usually the cheaper move once you have more than one project.
Signing up takes an email address and a crypto top-up: no card, no KYC, no phone number. If the bot is a hobby project you do not want attached to your personal billing details, that is the practical reason people do it this way.