Discloud YAML Config: Memory, Restart, and Sharding Trade‑offs
Discloud’s disploud.config YAML enforces memory limits, restart policies, and runtime entry points for Discord bots and web services; this post shows how to size a sharded bot, avoid OOM, and work within the platform’s guardrails.
02 May 2026, 01:25 UTC

The problem with explicit resource contracts
Most platform‑as‑a‑service offerings let you write a Dockerfile, a Procfile, or a separate CI pipeline. That flexibility can make debugging a midnight OOM kill a guessing game. Discloud takes a different approach: a single discloud.config YAML file is the entire deployment contract. No Dockerfile, no custom start command, no separate pipeline YAML. This constraint forces you to make resource decisions upfront — and reveals exactly where the platform’s guardrails help and where they chafe.
The manifest as a runtime contract
The discloud.config file declares the fields that matter at runtime:
version— major.minor only (e.g.,node: 20,python: 3.11)main— entry file relative to repo rootmemory— hard limit in MB, enforced by cgroupsrestart—on-failure,always, ornevername— app identifier
Discloud derives the start command from version and main: node main.js, python3 main.py, java -jar main.jar, or ./main for Go binaries. You cannot override this entrypoint. If your bot needs a pre‑start migration or a specific Node flag (--max-old-space-size), you’re out of luck — the platform controls the process start.
Environment variables are injected at container start from the dashboard or CLI (discloud env set KEY=value). They are not baked into the image, so rotating a Discord token or database password does not require a rebuild. However, you cannot reference secrets at build time — only at runtime.
Memory limits as a forcing function
The memory field is not a suggestion. It maps directly to a container cgroup limit. Exceed it and the kernel OOM‑kills your process. The restart policy then decides what happens next:
on-failure: restarts only when the process exits with a non‑zero code.always: restarts even on clean exits.never: leaves the app down.
This changes how you write code. A memory leak that would slowly swell a container on other platforms becomes an immediate, visible restart loop on Discloud. You must size your heap correctly. For a Node.js Discord bot using discord.js, a 256 MB limit typically handles 50‑100 guilds with moderate caching. Push past that and you’ll see OOM kills in discloud logs --follow within hours.
Worked example: sizing a sharded bot
Suppose you’re running a Discord bot that needs to cover 2 000 guilds. Discord recommends one shard per ~2 500 guilds, but you want headroom — so two shards. On Discloud you cannot run a Node cluster master with multiple workers in a single app; the platform does not support multi‑process workers within one container. Each shard must be a separate Discloud app with its own discloud.config and memory allocation.
# shard-0/discloud.config
name: mybot-shard-0
version: node: 20
main: index.js
memory: 256
restart: on-failure
# shard-1/discloud.config
name: mybot-shard-1
version: node: 20
main: index.js
memory: 256
restart: on-failure
Each shard gets 256 MB. Total platform memory consumption: 512 MB — still within the free tier’s 512 MB ceiling per app, but you are now using two app slots. The shards coordinate via Redis (external, since the filesystem is ephemeral). You deploy by pushing both directories to the same repo; Discloud’s GitHub integration detects changes per app path.
Verification: after deploy, run discloud logs --follow --app mybot-shard-0 and confirm the process starts with NODE_OPTIONS unset (Discloud does not inject Node flags). Check process.memoryUsage().heapUsed in your code and log it periodically — you’ll see the hard ceiling at ~240 MB before OOM.
Where the guardrails become walls
- No custom Dockerfiles. You’re locked to Discloud’s maintained runtime images. If your bot needs a native dependency (e.g.,
canvasfor image generation), you depend on Discloud’s base image having the right system libraries. Their patch cadence controls when you get security updates — you cannot pin a specificnode:20.12.0-slimdigest. - Version field is major.minor only.
version: node: 20means Discloud chooses the patch. A silent patch upgrade could introduce a breaking change in a native module. There’s nopackage-lock.jsonequivalent for the runtime. - Free‑tier restart quota.
restart: alwayscombined with a crash‑loop burns through the monthly restart allowance, leading to temporary suspension. Useon-failureand fix the crash instead. - Ephemeral filesystem. Any SQLite database, downloaded assets, or log files vanish on restart or deploy. You need external storage (S3, managed PostgreSQL, Redis) from day one.
Actionable closing: verify your contract before you push
- Create a minimal repo with your
discloud.configand entry file. - Push to a test GitHub repo and link it in the Discloud dashboard.
- Watch the build log: confirm the detected runtime matches
versionand the start command matchesmain. - Run
discloud logs --followand verify your environment variables appear at process start (look forDISCORD_TOKEN=***in the first 10 lines). - Intentionally exceed memory: allocate a 300 MB buffer in a 256 MB app. Confirm OOM kill + restart behavior matches your
restartpolicy. - Check the docs.discloud.app for the current runtime version matrix and free‑tier quotas — they change.
Discloud’s YAML‑first model trades operational flexibility for predictability. If your architecture fits within its constraints — single‑process, stateless, externally‑backed services — the platform removes entire classes of deployment drift. If you need custom runtimes, multi‑process workers, or build‑time secrets, you’ll hit the walls fast. Know which side of that line your project lives on before you commit.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.