Discloud Architecture Decision Guide: When the PaaS Fits and When It Doesn't
An architecture decision guide for Discloud: maps the PaaS's hard constraints—ephemeral storage, single-region hosting, vertical-only scaling, no SLA—to concrete engineering requirements so you can decide before committing code.
17 Dec 2025, 00:43 UTC

The Decision Context
You're evaluating Discloud for a Discord bot or small web service. The platform promises zero-config container hosting with a CLI workflow, but the constraints—ephemeral storage, single-region hosting, vertical-only scaling, and no published SLA—create hard boundaries. This note maps those boundaries to concrete architectural requirements so you can decide before committing code.
Requirements That Align With Discloud
- Stateless workloads that externalize all persistence to managed databases (PostgreSQL, MongoDB, Redis add-ons) or object storage.
- Single-region tolerance: users and dependencies located in or near São Paulo, Brazil, or latency above ~150 ms is acceptable.
- Predictable, low traffic: sustained CPU under 0.5 vCPU and RAM under 512 MB (free tier) or the paid tier limits (1–4 vCPU, 1–8 GB RAM).
- No horizontal scaling need: one container instance handles peak load; traffic spikes are absorbed by vertical plan upgrades.
- Operational simplicity over observability: 24-hour log retention via CLI is sufficient; no requirement for structured log export, metrics pipelines, or alerting integrations.
Smallest Suitable Design
For a Discord bot, the minimal viable deployment looks like:
# Dockerfile (if not using auto-detect)
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
ENV PORT=3000
CMD ["node", "index.js"]
Deploy via CLI:
discloud login # stores token in ~/.discloud/config (plaintext)
discloud create # provisions container + edge routing
discloud env set DISCORD_TOKEN=... DATABASE_URL=...
discloud upload # builds image, starts container, runs health check
The health check expects TCP port 3000 and an HTTP GET / response within 30 seconds. Three consecutive failures mark the app as crashed. A Discord bot that only opens a WebSocket to Discord's gateway will fail this check unless it also binds an HTTP server on PORT.
Trust and Data Boundaries
| Boundary | Discloud Responsibility | Your Responsibility |
|---|---|---|
| Container isolation | Docker-level CPU/RAM limits, network namespace | Application security, dependency updates |
| Secrets at rest | Platform-level controls only (no per-secret encryption) | Rotate tokens if ~/.discloud/config or dashboard compromised |
| Persistent data | Managed DB add-ons (shared instances) | Schema, backups, connection pooling, encryption in transit |
| Ephemeral filesystem | Wiped on every deploy/restart | Never write SQLite, session files, uploads, or caches locally |
| Network edge | Shared reverse proxy, SNI/Host routing, Let's Encrypt TLS | CNAME to app.discloud.app; no wildcard subdomains |
| DDoS protection | Basic rate limiting at edge proxy | Application-level rate limiting, Discord gateway backoff |
Operational Checks to Run Before Production
- Health-check validation: Deploy a test build that logs the incoming
GET /request. Confirm the container passes the 30-second window under cold start.discloud logs -f | grep "GET /" - Resource saturation test: Use
hey -n 1000 -c 50 https://your-app.discloud.app/while watching the dashboard CPU/RAM graphs. Verify the container stays under plan limits and the edge proxy doesn't return 502s. - Ephemeral storage proof: Write a file in
/app/temp.txt, rundiscloud restart, thendiscloud exec ls /app/temp.txt(or SSH equivalent) to confirm loss. - Log retention window: Generate distinct log lines, wait 25 hours, run
discloud logsand verify they are gone. - Custom domain TLS: Add
CNAME bot.example.com app.discloud.appin DNS, attach in dashboard, confirm certificate issuance and HTTPS access.
Failure Modes and Mitigations
| Failure Mode | Symptom | Mitigation |
|---|---|---|
| Health-check timeout | App marked crashed after 3 retries; Discord bot appears offline | Bind HTTP server on PORT responding 200 OK at /; keep WebSocket connection logic separate |
| OOM kill | Container restarts, logs show Killed or exit code 137 | Profile memory locally; add --max-old-space-size for Node; upgrade plan |
| Database noisy neighbor | Query latency spikes, connection pool exhaustion | Use connection pooling (PgBouncer, Prisma pool); monitor add-on metrics; consider external managed DB |
| Edge proxy rate limit | 429 responses during traffic burst | Implement application-level backoff; cache responses; move to external CDN if needed |
| Region outage | All apps in São Paulo data center unreachable | No multi-region failover on Discloud; design for graceful degradation or migrate critical workloads |
| CLI token leak | Unauthorized deployments, env var exposure | Store token in CI secret store; rotate via discloud login on new machine; revoke old sessions |
Conditions That Would Change the Design
- Persistent local state required (SQLite, file uploads, session files) → move to a VPS, Fly.io, or Render with persistent volumes.
- Global low-latency requirement → use a multi-region platform (Fly.io, Railway, Cloudflare Workers) or add a CDN layer.
- Horizontal scaling needed (multiple replicas for resilience or throughput) → Discloud does not support this; evaluate Kubernetes, ECS, or Nomad.
- Compliance or data residency mandates → single-region Brazil hosting may violate GDPR, LGPD, or sector rules; verify Terms of Service and Privacy Policy.
- Observability integration required (Datadog, Grafana Loki, OpenTelemetry) → no structured log export; consider sidecar log forwarder (adds complexity) or switch platform.
- SLA-backed uptime needed → no published SLA; negotiate enterprise terms or choose a provider with financial guarantees.
Quick Litmus Test
If you answer "yes" to all five, Discloud is a reasonable default:
- Can the service run entirely from environment variables and external databases?
- Is São Paulo latency acceptable for 95% of users?
- Does peak load fit within a single container's vertical limits?
- Is 24-hour CLI-only log access sufficient for debugging?
- Can you tolerate best-effort uptime with no financial SLA?
Any "no" means you should prototype the alternative before committing.
Verification Checklist for Your First Deploy
# 1. Create minimal repo
mkdir test-bot && cd test-bot
npm init -y && npm i discord.js
cat > index.js <<'EOF'
const { Client, GatewayIntentBits } = require('discord.js');
const express = require('express');
const app = express();
app.get('/', (_, res) => res.send('ok'));
const server = app.listen(process.env.PORT || 3000);
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.login(process.env.DISCORD_TOKEN);
EOF
# 2. Deploy
discloud login
discloud create
discloud env set DISCORD_TOKEN=your_token_here
discloud upload
# 3. Verify
discloud logs -f # watch for "ok" on GET /
discloud ps # confirm RUNNING status
curl https://your-app.discloud.app/ # should return "ok"
# 4. Stress
discloud exec "node -e 'setInterval(() => {}, 1000)'" # simulate load
discloud logs -f # watch for OOM or health-check failures
# 5. Cleanup
discloud delete --force
Run this sequence in a disposable environment. The output confirms whether the platform's constraints match your mental model before you invest in application code.