What Fits in 256 MB? Running Bots on the Free Tier
Real memory numbers for bots on a 256 MB free plan, what pushes usage up, and concrete techniques to keep Discord and Telegram bots lean enough to fit.
On this page
256 MB of RAM sounds tiny next to a laptop with 16 GB. For a bot, it’s often plenty. The trick is knowing what consumes memory and keeping those things in check. This article gives real numbers, explains where memory goes, and lists the techniques that keep a bot comfortably inside a free plan.
Real numbers
Typical idle memory, measured on real bots running on Kerit Cloud’s free tier:
| Bot | Setup | Memory |
|---|---|---|
| Telegram bot | aiogram, long polling | ~70 MB |
| Moderation bot | discord.js, ~10 servers | ~95 MB |
| Utility bot | discord.py, slash commands | ~110 MB |
| Economy / levels bot | Node.js + MySQL | ~140 MB |
| Music bot | Voice client, in-process audio | 300 MB+ — doesn’t fit |
The first four leave healthy headroom under 256 MB. The music bot doesn’t fit, because decoding and encoding audio in-process is memory- and CPU-hungry.
The 70% rule
Aim to keep steady-state memory under about 70% of your limit — roughly 180 MB on a 256 MB plan. Memory spikes during startup (when every server loads), during bursts of commands, and when a large server adds your bot. A bot idling at 230 MB will eventually spike past 256 MB and be killed. The watchdog restarts it, but frequent restarts mean missed commands.
Where the memory goes
1. The runtime
Before your code does anything, the runtime needs memory:
- Node.js: roughly 30–50 MB.
- Python: roughly 20–40 MB, more as you import libraries.
- Java: the JVM starts much higher — often 100–150 MB for a small app — which makes 256 MB tight for Java bots. A paid plan with 512 MB or 1 GB suits them better.
2. Your libraries
Every dependency you import loads code into memory. Large frameworks, image libraries and SDKs you use for one small feature all add up. Audit your dependencies occasionally and remove what you don’t use.
3. The cache
For Discord bots this is usually the biggest item. Libraries cache servers, channels, roles, members and messages to avoid API calls. Caches grow with the number and size of servers your bot is in. Trimming them is the most effective memory fix available — see below.
4. Your data
Lists and dictionaries that grow forever — every message logged, every user’s stats held in memory, unbounded caches you wrote yourself — are the classic slow leak. Move persistent data into a database, which the free plan includes.
Techniques that work
Trim Discord caches
discord.js:
const { Client, GatewayIntentBits, Options } = require('discord.js');
const client = new Client({
intents: [GatewayIntentBits.Guilds],
makeCache: Options.cacheWithLimits({
...Options.DefaultMakeCacheSettings,
MessageManager: 0,
PresenceManager: 0,
ReactionManager: 0,
GuildMemberManager: { maxSize: 100, keepOverLimit: (m) => m.id === m.client.user.id },
}),
});
discord.py:
intents = discord.Intents.default()
bot = commands.Bot(
command_prefix=commands.when_mentioned,
intents=intents,
max_messages=None, # disable the message cache
member_cache_flags=discord.MemberCacheFlags.none(),
)
Only do this if your features don’t depend on those caches — a bot that logs deleted messages needs a message cache, for example. Full guides: reducing memory usage in discord.js bots and in Python bots.
Request fewer intents
Every intent means more events and, often, more cached objects. The presence intent is the heaviest by far. Slash-command bots often need nothing beyond the guilds intent. See gateway intents explained.
Use slash commands
Slash commands deliver their arguments directly, without the Message Content intent or a message cache. Moving from prefix commands to slash commands usually lowers memory as a side effect.
Keep data in the database
Store balances, settings and logs in MySQL instead of holding them in memory. Query what you need when you need it. The free plan’s shared MySQL database is made for exactly this — see using the shared MySQL database.
Load lazily
Don’t load every feature, dataset or large file at startup. Import heavy modules inside the command that uses them, and read large files on demand.
Stream instead of buffering
Download files to disk and process them in chunks rather than reading whole files into memory. For Telegram bots handling media, this matters a lot — see handling files and media.
Measuring your bot
Check the memory graph in the panel after the bot has run for a while — the steady-state figure matters, not the first minute. You can also log memory periodically:
setInterval(() => {
console.log(`RSS ${(process.memoryUsage().rss / 1048576).toFixed(0)} MB`);
}, 10 * 60 * 1000);
import resource
peak_mb = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1024 # KB → MB on Linux
A line that climbs steadily and never levels off indicates a leak: an event listener added repeatedly, a collection that only grows, or objects held in closures. More RAM only delays the crash; fix the leak.
What won’t fit — and that’s fine
Some bots genuinely need more than 256 MB:
- Music bots — even with Lavalink handling audio, busy music bots want more headroom. Run the bot on a paid plan and the audio on a Lavalink node.
- Bots in hundreds of servers with member caches they rely on.
- Java bots with meaningful workloads.
- AI bots holding conversation history or embeddings in memory.
- Image generation with canvas or Pillow at scale.
For these, the next step up is Basic (512 MB) or Pro (1 GB) on the Discord bot plans, or Starter (1 GB) for Telegram. Upgrades happen in place, so nothing needs redeploying.
Summary
256 MB comfortably runs single-purpose Discord and Telegram bots — measured bots sit between 70 and 140 MB. Keep steady-state usage under about 180 MB by trimming library caches, requesting only the intents you need, preferring slash commands, keeping data in the included database and streaming files instead of buffering them. Measure over time, fix leaks rather than feeding them, and move to a paid plan when your bot’s features genuinely need more.