frontback / runtimes / go

Deploy a Go app

Example HTTP server in Go, deployed to a URL in Europe in a minute. What it costs to run, how to scale it out when one instance stops being enough, and what cgo changes.

Basic app example

Standard library, one file, reads PORT from the environment with a local default. Nothing here is Frontback specific.

main.go
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "Hello from Go on Frontback")
	})
	fmt.Println("Serving on localhost:" + port)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}

Run it locally first; there is nothing more to it:

$ go mod init hello && go run .
Serving on localhost:8080

Prerequisites

Two things, once per machine. The CLI is a single self-contained binary with no runtime and no daemon behind it, and the login is a device code, so it works over SSH and inside a container just as well.

$ brew install frontback/tap/frontback

$ frontback login
  open the URL it prints and enter QK7X-4M2P
 logged in as anna@acme.eu (organization acme)

The Go toolchain route works anywhere, whichever system you are on, and the binary is self-contained either way.

For CI, or anything else running unattended, use an API key instead of a device login: frontback login --with-token, or put FRONTBACK_TOKEN in the environment and store nothing at all. A key can be narrower than the person who made it.

Deploy it from your terminal

frontback deploy detects Go from go.mod, compiles a static binary and ships it on a distroless base a couple of megabytes small. No Dockerfile, no YAML; open the URL it prints and your server is answering.

$ frontback deploy

  created project hello-go
  service   hello-go  production
> building
 built (1.4s)
 artifact 3f9c21aa 6.1 MiB
 v1 released to production
 live (0.9s)
  https://hello-go.run.frontback.eu

Or deploy on git push

Connect the repository (GitHub App, Gitea, or a deploy key), bind it to your project and track a branch per environment. A push deploys only the services the commit changed, grouped into one release: staging first, production one promote away, rollback one more.

Configuration, when you need it

The deploy above needed zero config. When you outgrow the defaults, frontback.json is the whole surface:

"go": "1.26"
Pins the toolchain. The ladder is frontback.json, then the toolchain line in go.mod, then the go directive as a minimum. The catalog holds 1.26 (default) and 1.25 (maintenance); nothing is downloaded mid-build.
"build" + "start"
Take over compilation entirely. Everything your build writes to dist/ lands in the image, and start is shell form, so $PORT interpolates.
"env"
Where GOFLAGS, build tags and CGO_ENABLED overrides go. Merged last, so it wins.

Which package is the entry? cmd/<module-name> first, then the module root, then common names like server or api. More than one candidate is an error that names them, never a coin flip. And none of this is magic you have to trust: frontback pack explain prints the exact build plan before anything runs.

When one instance is not enough

Make the machine bigger, or run more copies of it. Both are settings on the service in the console, and both take effect through an ordinary release, so staging sees the change before production does and a rollback is one click.

A bigger machine
Shared 256 MB through Shared 2 GB share cores with neighbours and burst into whatever is idle; the Performance sizes pin cores to your microVM instead. A resize is a restart: it mints a release like any deploy, so it promotes and rolls back the same way.
More replicas
A replica is a warm sandbox kept ready for the service, and the floor is never reaped when traffic stops. 1 on Free, 5 on Pro, 20 on Business, 100 on Enterprise.
Always on
Turn off idle stop when a cold start is not acceptable, from Pro up. Everything below it sleeps when nobody is asking and costs nothing while it sleeps.

What it costs

  • Free, €0Runs your Go service on demand: it stops when idle and costs nothing asleep.
  • €4 a monthA static Go binary fits Shared 256 MB, the smallest machine, always-on.
  • Pro, €19 a month Always-on and every shared machine size start on Pro.

Where Go shines here, and where it does not

  • A tiny memory footprint: an idle net/http server sits in single-digit megabytes, so it fits the smallest, cheapest machine with room to spare.
  • Instant startup: a static binary has no runtime to warm up, so cold starts are barely visible and scale-to-zero costs you nothing in wake-up time.
  • One artifact: dependencies compile in, the whole deploy is a few megabytes, and there is no node_modules to ship or cache.
  • cgo complicates the static story: one C-backed dependency moves you to a glibc base image. The build names the culprit, and there is usually a pure-Go swap.
  • Every change is a compile. The instant save-to-live loop of the web editor belongs to TypeScript; with Go, the fastest iteration stays on your machine.

Examples in Go

Start from a working product

All examples

Every template deploys into your organisation as a real project, live at its own URL. Then it is yours: open the editor and change anything, or tell the AI what you want instead.

Go link checker
A Go service in one file: check any URL's status and latency.

Questions Go developers actually ask

No. <code>frontback deploy</code> detects Go from your go.mod, compiles a static binary and ships it on a distroless base on its own. If you commit your own Dockerfile, it wins over the built-in Go plan.

Go 1.26 by default, with 1.25 available for maintenance. Pin it with <code>{&quot;go&quot;: &quot;1.26&quot;}</code> in frontback.json or via the toolchain line in go.mod; the go directive in go.mod is treated as a minimum, not a pin, and nothing is downloaded mid-build.

Read <code>PORT</code> from the environment and fall back to 8080 locally. Frontback injects PORT at runtime and routes traffic to it, so the snippet on this page works unchanged in both places.

Yes. A known cgo dependency like mattn/go-sqlite3 automatically switches the runtime image to a glibc distroless base, and the build tells you which package caused it, with modernc.org/sqlite as the pure-Go swap if you want to stay fully static. For serverless, though, we recommend the managed libsql database: it speaks the SQLite dialect over HTTP, so there is no connection pool to exhaust and nothing to keep alive between requests.

Yes. Connect the repository (GitHub App, Gitea, or a deploy key), track a branch per environment, and every push deploys the services the commit changed as one release: staging first, production one promote away.

A small Go service fits Shared 256 MB, the smallest machine, at €4 a month always-on. Always-on starts on the Pro plan (€19 a month); the Free plan runs services on demand and stops them when idle. Every price is on the pricing page, not behind a sales call.

On our own data servers in the EU. EU hosting is the default on every plan, not a paid add-on, which is usually the answer your compliance team is looking for.

Deploy something else

Go beyond what seems possible.