Deploying Go, Bun and Deno Apps on the Free Tier
Run Go, Bun and Deno bots and services on a free server — building binaries, start commands, permissions, memory tips and when each runtime makes sense.
On this page
Node.js and Python dominate bot development, but they’re not the only options. Go, Bun and Deno each bring real advantages — tiny memory footprints, fast startup, built-in TypeScript — and Kerit Cloud’s free tier supports all three. This guide covers how to deploy each and why you might choose them.
Why consider an alternative runtime?
On a 256 MB plan, the runtime’s own overhead matters:
| Runtime | Strengths | Typical baseline memory |
|---|---|---|
| Go | Compiled single binary, very low memory, great concurrency | Very low — often 10–20 MB for a small service |
| Bun | Fast startup, runs TypeScript directly, Node.js-compatible | Low to moderate |
| Deno | TypeScript built in, secure-by-default permissions, npm support | Moderate |
| Node.js | Largest ecosystem, most bot libraries | ~30–50 MB |
Go in particular stretches a free plan much further: its compiled binaries use a fraction of the memory of an interpreted runtime, leaving more room for your data.
Deploying a Go app
Build a static binary
Go compiles to a single executable. Build it for Linux on the same CPU architecture as the server (x86-64 for AMD EPYC):
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-s -w" -o bot .
CGO_ENABLED=0produces a fully static binary with no C library dependencies, so it runs on any Linux.-ldflags="-s -w"strips debug information, making the binary smaller.
Upload the bot binary and make sure it’s executable (chmod +x bot if your upload tool doesn’t preserve permissions). Set the start command to ./bot.
Alternatively, upload your source with go.mod and go.sum and build on the server during startup — convenient, but compiling uses CPU and time on each deploy, which is slower on a 30% CPU share. Building locally or in CI is usually better.
A minimal Discord bot in Go
With the popular discordgo library:
package main
import (
"log"
"os"
"os/signal"
"syscall"
"github.com/bwmarrin/discordgo"
)
func main() {
dg, err := discordgo.New("Bot " + os.Getenv("DISCORD_TOKEN"))
if err != nil {
log.Fatal(err)
}
dg.Identify.Intents = discordgo.IntentsGuilds
dg.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) {
log.Printf("Ready as %s", r.User.Username)
})
if err := dg.Open(); err != nil {
log.Fatal(err)
}
defer dg.Close()
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
<-stop
log.Println("Shutting down")
}
The signal handling means restarts and redeploys close the gateway connection cleanly. For Telegram, libraries such as go-telegram/bot and telebot (the Go one) follow similar patterns.
Go memory tips
Go’s garbage collector is tuned for throughput and may let the heap grow before collecting. On a small plan, set a soft memory limit so the runtime collects more aggressively as it approaches your ceiling:
GOMEMLIMIT=180MiB ./bot
GOMEMLIMIT (Go 1.19+) is a soft limit — the GC works harder near it — so set it comfortably below your plan’s 256 MB. You can set it as an environment variable in the panel.
Deploying a Bun app
Bun runs JavaScript and TypeScript directly and is largely compatible with Node.js packages, including discord.js and grammY.
- Upload your project with
package.json(andbun.lockbif you use it). - Dependencies install on the server with Bun’s fast installer.
- Set the start command:
bun run index.ts
No build step is needed for TypeScript — Bun transpiles on the fly. Environment variables are available through process.env or Bun.env, and Bun also loads .env files automatically in development (don’t upload yours; use panel variables in production).
A few Node.js APIs and native addons behave differently under Bun, so test your bot locally with Bun before deploying. Most pure-JavaScript bot libraries work unchanged.
Deploying a Deno app
Deno runs TypeScript natively and is secure by default: a script can’t access the network, environment variables or files unless you grant permission.
A minimal grammY Telegram bot in Deno:
import { Bot } from "npm:grammy";
const bot = new Bot(Deno.env.get("BOT_TOKEN")!);
bot.command("start", (ctx) => ctx.reply("Hello from Deno!"));
bot.catch((err) => console.error(err));
Deno.addSignalListener("SIGTERM", () => bot.stop());
bot.start();
Start it with only the permissions it needs:
deno run --allow-net --allow-env main.ts
If the bot writes files (SQLite, logs), add --allow-read and --allow-write, ideally scoped to a folder: --allow-write=./data. Granting only what’s needed means a compromised dependency can’t do much.
Deno can import npm packages with the npm: specifier, so many Node.js libraries are usable. Dependencies are cached on first run — the persistent disk keeps the cache across restarts, so later starts are quick.
Which should you choose?
- Choose Go if you want the lowest memory and CPU use, simple deployment of one binary, and you’re happy with a statically typed language. Excellent for bots that need to handle a lot on a small plan.
- Choose Bun if you like the Node.js ecosystem and want faster installs and startup with native TypeScript.
- Choose Deno if you value TypeScript without configuration and security through explicit permissions.
- Stay with Node.js or Python if your library of choice is only well supported there — discord.js, discord.py and aiogram have the largest communities and the most examples.
Common issues
exec format error — the Go binary was built for the wrong OS or architecture. Build with GOOS=linux GOARCH=amd64.
permission denied when starting a Go binary — the file isn’t executable. Set the executable bit.
Deno PermissionDenied — add the missing --allow-* flag the error names.
A package fails under Bun — check whether it relies on a Node.js API Bun hasn’t implemented, and test locally with the same Bun version.
Summary
Kerit Cloud’s free tier runs Go, Bun and Deno as well as Node.js and Python. Deploy Go as a static Linux binary built with CGO_ENABLED=0 and cap its heap with GOMEMLIMIT; run Bun projects directly with bun run; and start Deno apps with only the --allow-* permissions they need. Go stretches 256 MB furthest, Bun and Deno make TypeScript effortless, and all three handle SIGTERM for clean restarts.