Guide 10

Hosting bots: VPS, containers, PaaS and serverless compared

The right host depends on one question: does your bot need a process that is always running, or can it wake up per request?

Guide3 min readUpdated

Match the runtime to the delivery model

Bot type Needs Good fits
Webhook-only (Telegram webhook, Discord HTTP interactions, Slack Events, WhatsApp) An HTTPS endpoint Serverless functions, edge workers, any web host
Long polling (Telegram getUpdates) Always-on process VPS, container platform, PaaS worker
Gateway or Socket Mode (Discord Gateway, Slack Socket Mode) Always-on process with a WebSocket VPS, container platform, PaaS worker
Heavy AI or media processing CPU or GPU, memory VPS, container platform, a separate job queue
Scheduled jobs A scheduler Cron Triggers, cloud schedulers, GitHub Actions, systemd timers

Options in detail

Serverless and edge (Cloudflare Workers, AWS Lambda, Google Cloud Run, Deno Deploy). You pay per request, it scales to zero, and TLS is included. Limits on execution time and no persistent sockets mean you design around webhooks, queues and external state. Excellent for most chat bots. See Cloudflare Workers for bots.

Platform as a service (Render, Railway, Fly.io and similar). Push a repository or a container and get a running service, background workers, logs and managed databases. A good middle ground for Gateway bots.

VPS (Hetzner, DigitalOcean, OVHcloud, Linode and others). Full control and predictable cost from a few dollars a month. You are responsible for updates, firewall, TLS, process supervision and backups.

Your own computer is fine for development. For production it loses power, network and sleep battles; use a tunnel only for testing.

Running on a VPS with systemd

# /etc/systemd/system/mybot.service
[Unit]
Description=My Discord bot
After=network-online.target
Wants=network-online.target

[Service]
User=mybot
WorkingDirectory=/opt/mybot
EnvironmentFile=/etc/mybot.env
ExecStart=/usr/bin/node dist/index.js
Restart=always
RestartSec=5
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/opt/mybot/data

[Install]
WantedBy=multi-user.target
sudo useradd --system --home /opt/mybot mybot
sudo chmod 600 /etc/mybot.env
sudo systemctl daemon-reload && sudo systemctl enable --now mybot
journalctl -u mybot -f

The bot runs as an unprivileged user, restarts on crash, reads secrets from a root-owned file, and has a read-only view of the system.

Running with Docker Compose

services:
  bot:
    build: .
    restart: unless-stopped
    env_file: .env            # never commit this file
    read_only: true
    tmpfs: [/tmp]
    depends_on: [redis]
    healthcheck:
      test: ["CMD", "node", "healthcheck.js"]
      interval: 30s
      retries: 3
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    volumes: [redis-data:/data]
volumes:
  redis-data:

Use a small base image, run as a non-root user in the Dockerfile, and pin dependency versions with a lockfile.

Webhooks on a VPS

Put a reverse proxy (Caddy, nginx) in front of your app for TLS, or use a tunnel such as Cloudflare Tunnel so you do not open inbound ports at all. Only expose the webhook paths; keep admin dashboards on localhost or behind authentication.

Operations checklist

  • Health: a /healthz endpoint for webhook services, or a heartbeat for workers that an external monitor checks.
  • Logs: structured JSON to stdout, collected by journald, the platform or a log service. Redact tokens and personal data.
  • Alerts: on crash loops, error rate, queue depth and webhook silence (no events for an unusual period).
  • Backups: databases and any local state, with a tested restore.
  • Updates: automatic OS security updates, regular dependency updates, and a reproducible deploy.
  • Single instance: only one process should poll getUpdates or hold a Gateway session per shard. Two copies cause conflicts and duplicate replies.

Cost tips

A typical community bot with webhooks costs nothing on free serverless tiers. Gateway bots fit in a few hundred megabytes of RAM on a small VPS. The expensive parts are usually AI model calls and media processing: measure them separately and put quotas in place before you go viral.

Check your understanding

1. Which bot type fits serverless best?
2. Why run only one getUpdates poller?