Every bot starts the same way: it runs on a laptop, the laptop sleeps, and the bot goes offline during the one conversation it was written for. Moving it onto a hosted container fixes that, and introduces a different set of problems: the ones that only appear when something has been running for three weeks.
What the container is
Bot hosting here is a container on a game panel, with a reserved slice of CPU and memory, a disk for your code and dependencies, and a runtime of either Node.js or Python. You start, stop and restart it from the browser, read its console output live, and upload files or pull from a repository. Choosing between Node.js and Python covers the runtime decision; the rest of this is the same whichever you pick.
Staying up is a property of your code
The container will restart your bot when the process exits. That sounds like a safety net and is actually a trap, because a bot that crashes on every message will restart on every message and look, from the panel, like it is running.
- Handle the errors you expect. A rejected promise or an uncaught exception inside a command handler should log and return, not take the process down. Both runtimes let you register a top-level handler for the ones you miss; use it to log and keep going.
- Let the library reconnect. Discord drops gateway connections routinely. Both official libraries reconnect on their own. Code that exits on a disconnect turns a two-second blip into a cold start.
- Never call the exit function on a handled error. It is the fastest way to build a restart loop.
- Respect the rate limits. The libraries queue for you; code that bypasses the client to call the API directly does not get that for free.
Secrets belong in environment variables
Your bot token is the whole account. Put it in an environment variable through the panel's startup settings and read it from there (process.env.DISCORD_TOKEN or os.environ["DISCORD_TOKEN"]) rather than in a file in the repository. Two reasons beyond the obvious one: a token in a public repository is found by scrapers within minutes, and a token that lives only in the environment is not in a backup archive that you might later download onto a machine you share. Keep a copy of those variables somewhere safe, because they are configuration rather than files and they are not in the backup either.
Logs and memory
Write to standard output and standard error, not to a log file that grows until the disk is full. The panel shows the console live, which is where you will diagnose almost everything. If you want history, log at a level you can actually read later: a line per command, not a line per event.
Memory is where long-running bots fail. The usual cause is a cache that is never pruned: a message collection, a map keyed by user, a queue of items that are added and never removed. If memory climbs steadily over days and never falls, you have one of those. Restarting hides it; finding it fixes it.
The free weekly backup, and what it does when the slots fill
Every bot plan carries a free weekly backup. A schedule is created on your container automatically, runs once a week in the early hours, and the day and minute are spread per container so a node does not try to archive everything it holds at the same moment. You do not have to switch it on.
The part worth understanding is what happens when the backup slots are full. A scheduled backup normally makes room by deleting the oldest unlocked backup, and that rule, left alone, would eventually eat the snapshot you took by hand before an upgrade. So we do not leave it alone: our automation never deletes a backup. When the slots are full and the one the panel would remove is not the one our own last run made, the weekly schedule switches itself off and switches back on when a slot frees. Your service page shows how many slots are in use, when the last backup ran, when the next one is due, and whether the schedule is currently paused because your own backups are using every slot.
Two habits follow from that. Lock any backup you want to keep, which takes it out of the deletion rule entirely. And before anything destructive, take a backup and download it: a copy that exists only inside the container you are about to rebuild is not a backup. The free weekly backup lists exactly what the archive contains and, more usefully, what it does not.
The two buttons that delete things
Reinstall runs the installation script again and may change or remove files. Change runtime rebuilds the container from scratch and deletes everything on it. Neither can be undone. Restarting and reinstalling explains when each is the right tool.
The habit that makes all of this cheap
Keep the source in a version control repository and treat the container as disposable. Backups then only have to carry the data, the token lives in the environment, and a container you have somehow destroyed is twenty minutes of work instead of a rewrite from memory.