> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sevalla.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> These are the docs for Sevalla, a platform for deploying applications, databases, static sites, object storage and load balancers. The dashboard is at https://app.sevalla.com.
> Bold text in steps is an exact dashboard label.
> To act on a Sevalla account, prefer the Sevalla MCP server (https://mcp.sevalla.com/mcp, see https://docs.sevalla.com/ai-agents/overview.md), then the Sevalla CLI (https://docs.sevalla.com/developer-tools/cli.md), then the REST API (https://api-docs.sevalla.com, OpenAPI spec at https://api.sevalla.com/v3/openapi.json).
> Every page index is at https://docs.sevalla.com/llms.txt.

# Deploy Go applications

> How Go applications build and run on Sevalla with Ingot: module detection, the go and toolchain lines, static binaries, the PORT variable, processes and Dockerfiles.

A Go web server runs on Sevalla as an [application](https://docs.sevalla.com/applications/overview.md): Sevalla builds an image from your Git repository, compiles your `main` package into a binary, and runs it as processes. The web process runs the binary that serves HTTP, background workers and cron jobs can run other binaries from the same module, and jobs run migrations before each deployment.

## Framework guides

> **[net/http](https://docs.sevalla.com/guides/go/net-http.md)**
>
> Deploy a JSON API on the standard library, with Go 1.22 routing patterns and a graceful shutdown.

> **[Gin](https://docs.sevalla.com/guides/go/gin.md)**
>
> Deploy Gin in release mode, with the visitor's IP address from Cloudflare's header.

> **[Echo](https://docs.sevalla.com/guides/go/echo.md)**
>
> Deploy Echo v5, which shuts down gracefully on its own.

> **[Fiber](https://docs.sevalla.com/guides/go/fiber.md)**
>
> Deploy Fiber v3, with the proxy settings that make `c.IP()` and `c.Scheme()` right.

## How Go applications run on Sevalla

| Part | On Sevalla |
| - | - |
| Build | [Ingot](https://docs.sevalla.com/applications/builds/ingot.md), Sevalla's builder, by default. It recognizes a Go project by `go.mod` or `go.work`, downloads the modules from `go.mod` and `go.sum`, then compiles each `main` package at the module's root and in `cmd/<name>` into `/usr/local/bin`, with `-trimpath -ldflags="-s -w"`. With a `vendor/modules.txt`, it builds from the vendored modules instead. |
| Modules | Go modules. When `go.mod` requires modules, commit `go.sum`: without it, the build fails with `go.mod requires modules, but go.sum is missing`. |
| Go version | Go 1.27, Ingot's default line, as long as the `toolchain` or `go` line in `go.mod` allows it. See [Pin the Go version](#pin-the-go-version). The build never downloads another Go: Ingot sets `GOTOOLCHAIN=local`. |
| cgo | Off, so binaries are static and need no C library. Ingot turns it on when a package in your module imports `"C"`, or when `go.mod` requires `github.com/mattn/go-sqlite3` or `github.com/confluentinc/confluent-kafka-go`. Set `CGO_ENABLED=1` as a build-time variable to turn it on yourself. |
| Start command | The binary of the `main` package at the module's root, such as `/usr/local/bin/storefront`, named after the last part of the module path. With no root package and one package in `cmd/`, that one. With several and none at the root, set the start command: Ingot builds every one of them into `/usr/local/bin`. See [Set the start command](https://docs.sevalla.com/applications/builds/ingot.md#set-the-start-command). |
| Port | Sevalla sets the `PORT` environment variable to the web process's port, `8080` by default. The server must listen on it, on all network interfaces, as `http.Server{Addr: ":" + os.Getenv("PORT")}` does. |
| Concurrency | One process serves every request on goroutines. For a module whose `go` line is 1.25 or later, Go sizes `GOMAXPROCS` to the instance's CPU limit. To serve more traffic, choose a larger size or add instances. See [Scaling](https://docs.sevalla.com/applications/scaling.md). |
| Shutdown | Sevalla sends `SIGTERM` to stop an instance. Handle it with `signal.NotifyContext` and `http.Server.Shutdown`, as in the [net/http guide](https://docs.sevalla.com/guides/go/net-http.md#shut-down-gracefully), so requests in progress finish. Ingot's image runs the binary under `tini`, which passes the signal on. |
| Image | Ingot builds on `golang:1.27-trixie` and runs the binary on `debian:trixie-slim`, with CA certificates and time zone data, as user `1000:1000`. |
| Runtime files | The binary runs from `/app`. Ingot copies the folders a Go server usually reads at runtime, `assets`, `locales`, `migrations`, `public`, `static`, `templates` and `views`, and `config` when it holds no Go code, from the module's root into `/app`, so relative paths such as `templates/index.html` work. Files you embed with `//go:embed` are part of the binary. |
| Migrations | A job with the start policy **Before deployment** that runs a migration binary or tool from the image. If it fails, the deployment fails and the previous version keeps running. |
| Workers | A background worker that runs another binary of the module, such as `/usr/local/bin/worker` built from `cmd/worker`. See [Run workers and jobs](https://docs.sevalla.com/applications/builds/ingot.md#run-workers-and-jobs). |
| Scheduled tasks | A cron job that runs a binary on a schedule. |
| Databases | PostgreSQL, MySQL, MariaDB, Redis or Valkey on Sevalla, reached over an [internal connection](https://docs.sevalla.com/databases/connect.md#connect-an-application) that adds the connection details as environment variables. |
| Files | The filesystem resets on every deployment. Keep uploads in [object storage](https://docs.sevalla.com/object-storage/overview.md), or attach a [disk](https://docs.sevalla.com/applications/disks.md). |
| Dockerfile | Switch the build strategy to [Dockerfile](https://docs.sevalla.com/applications/builds/dockerfile.md) on the application's **Settings** tab. See [Build with a Dockerfile](#build-with-a-dockerfile). |

Every process (web, worker, cron job and job) runs from the same image, each with its own start command. See [Processes](https://docs.sevalla.com/applications/processes.md) for every process type and its settings.

## Pin the Go version

The `go` line in `go.mod` is the oldest Go release that builds the module, and `go mod init` sets it to the release you run, such as `go 1.27.1`. Ingot builds on Go 1.27, its default line, whenever the module allows it, and on the newest maintained line that satisfies the module otherwise. A new Ingot release can move the default to a newer Go line, which Go's compatibility promise covers.

Ingot takes the version from the first of these that's set:

1. The `INGOT_GO_VERSION` environment variable, marked **Available during buildtime**, such as `1.26`.
2. `versions.go` in [ingot.json](https://docs.sevalla.com/applications/builds/ingot.md#configure-the-build), such as `{ "versions": { "go": "1.26" } }`.
3. The `toolchain` line, then the `go` line, of `go.work` when the repository has one, otherwise of `go.mod`. Both are minimums.

To stay on one Go line, set it in `ingot.json` or with `INGOT_GO_VERSION`: `1.26` builds on the newest Go 1.26 release. The build plan's **Go** row shows the version and where it came from, for example `go.mod "go 1.27.1"` or `ingot.json "1.26"`.

A `go` line newer than every Go release Ingot knows fails the build with `no go version in this Ingot release satisfies ">=1.28.0" (newest known: 1.27.3)`. Set the line to a release Ingot knows with `go mod edit -go=1.27.0`. See [Set the language version](https://docs.sevalla.com/applications/builds/ingot.md#set-the-language-version).

## Build with a Dockerfile

Ingot needs no Dockerfile, but you can write your own for full control of the image. A Dockerfile for Go on Sevalla builds in a `golang` image of the line `go.mod` asks for, copies `go.mod` and `go.sum` and runs `go mod download` before it copies the code, so a code change reuses the downloaded modules, and builds with `CGO_ENABLED=0`. The final stage needs the binary, `/bin/sh` for the [web terminal](https://docs.sevalla.com/applications/web-terminal.md) and custom start commands, and CA certificates, which `alpine` has, and runs as a user other than root. A server that handles `SIGTERM` itself needs no init process. Each guide has one: see [Gin](https://docs.sevalla.com/guides/go/gin.md#deploy-with-a-dockerfile) for a module with dependencies, and [net/http](https://docs.sevalla.com/guides/go/net-http.md#deploy-with-a-dockerfile) for one without.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.