Cloud Deploy Basics
10 examples to get you started with Cloud & Serverless - 7 basic and 3 intermediate.
Prerequisites
- Install Go 1.26.x or later from go.dev/dl.
- Install Docker for Cloud Run image builds and local container smoke tests.
- For AWS: install AWS SAM CLI or use the AWS Console zip upload flow; configure
aws configurewith a dev account. - For GCP: install gcloud and run
gcloud auth loginplusgcloud config set project <PROJECT_ID>. - Verify:
go version,docker version, and cloud CLI auth before deploying.
Basic Examples
1. Scaffold a Go Module for Cloud Targets
Create a module with separate cmd entrypoints for Lambda and HTTP.
mkdir greeter-cloud && cd greeter-cloud
go mod init example.com/greeter-cloud
mkdir -p cmd/lambda cmd/server internal/greetinternal/greetholds shared logic both adapters call.cmd/lambdausesgithub.com/aws/aws-lambda-go/lambda.cmd/serverexposes a normal HTTP server for Cloud Run.
Related: Go in the Cloud: Lambda, Cloud Run, and Beyond - platform mental model
2. Shared Greeting Logic
Keep handlers thin by delegating to a pure function.
package greet
import "fmt"
func Message(name string) string {
if name == "" {
name = "world"
}
return fmt.Sprintf("hello, %s", name)
}- No cloud imports in
internal/greet- unit tests stay fast. - Both Lambda and HTTP adapters import the same package.
Related: Architecture in Go: Small Interfaces, Explicit Dependencies - adapter boundaries
3. Minimal AWS Lambda Handler
Use the provided.al2023 runtime with a bootstrap binary name.
package main
import (
"context"
"example.com/greeter-cloud/internal/greet"
"github.com/aws/aws-lambda-go/lambda"
)
type Event struct {
Name string `json:"name"`
}
func handle(ctx context.Context, e Event) (string, error) {
return greet.Message(e.Name), nil
}
func main() {
lambda.Start(handle)
}lambda.Startregisters the handler with the runtime API.- Cross-compile with
GOOS=linux GOARCH=arm64 CGO_ENABLED=0.
Related: AWS Lambda Custom Runtime & provided.al2023 - ARM packaging
4. Build the Lambda Bootstrap Binary
Produce bootstrap for the provided runtime zip layout.
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -ldflags="-s -w" -o bootstrap ./cmd/lambda
zip function.zip bootstrap-ldflags="-s -w"strips debug symbols to shrink cold-start load time.- Zip must place
bootstrapat the archive root forprovided.al2023.
Related: AWS Lambda Custom Runtime & provided.al2023 - zip layout
5. Minimal Cloud Run HTTP Server
Listen on $PORT (default 8080) for Cloud Run compatibility.
package main
import (
"log"
"net/http"
"os"
"example.com/greeter-cloud/internal/greet"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
_, _ = w.Write([]byte(greet.Message(name)))
})
mux.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
})
addr := ":" + os.Getenv("PORT")
if addr == ":" {
addr = ":8080"
}
log.Fatal(http.ListenAndServe(addr, mux))
}- Cloud Run injects
PORT; local dev falls back to 8080. /healthsupports load balancer and platform probes.
Related: GCP Cloud Run & AWS Fargate Patterns - service configuration
6. Dockerfile for Cloud Run
Use a multi-stage build with a distroless runtime image.
FROM golang:1.26 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /server ./cmd/server
FROM gcr.io/distroless/static-debian12
COPY --from=build /server /server
ENV PORT=8080
EXPOSE 8080
ENTRYPOINT ["/server"]- Distroless removes shell attack surface while keeping CA certs for HTTPS clients.
- Build once locally; push the same image tag to Artifact Registry.
Related: GCP Cloud Run & AWS Fargate Patterns - container deploy
7. Deploy Cloud Run from the CLI
Build, push, and deploy in one flow.
gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT/REPO/greeter:latest
gcloud run deploy greeter \
--image REGION-docker.pkg.dev/PROJECT/REPO/greeter:latest \
--region REGION \
--allow-unauthenticated \
--port 8080--allow-unauthenticatedis for public demos only; lock down production services.- Confirm the service URL with
curl "$(gcloud run services describe greeter --region REGION --format='value(status.url)')?name=cloud".
Related: Secrets, IAM & Workload Identity - service account wiring
Intermediate Examples
8. SAM Template for the Lambda Function
Declare runtime, architecture, and handler in infrastructure as code.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
GreeterFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: provided.al2023
Architectures: [arm64]
Handler: bootstrap
CodeUri: .
MemorySize: 128
Timeout: 10
Events:
Api:
Type: Api
Properties:
Path: /greet
Method: getsam buildandsam deploy --guidedupload the zip and API Gateway route.- Tune
MemorySize- it also scales CPU on Lambda.
Related: Serverless Go Architecture Decision Guide - when Lambda fits
9. Local Lambda Invoke with SAM
Test the bootstrap binary before uploading.
sam local invoke GreeterFunction -e events/greet.json{"name": "sam"}events/greet.jsonis a sample payload checked into the repo.- Fix compile and JSON contract issues before paying for cloud iterations.
Related: Cloud & Serverless Best Practices - local parity habits
10. Structured Logs for Both Adapters
Use log/slog so CloudWatch and Cloud Logging parse JSON consistently.
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
slog.SetDefault(logger)
slog.Info("request", "name", name, "platform", "cloud-run")- Emit one JSON object per line from stdout/stderr.
- Include a request or trace ID when behind API Gateway or Cloud Run load balancers.
Related: Cloud & Serverless Best Practices - observability guardrails
Stack versions: This page was written for Go 1.26.x (Green Tea GC default, go fix modernizers - verify patch at build), chi (latest - verify at build), gin (latest - verify at build), echo (latest - verify at build), google.golang.org/grpc (latest - verify at build), sigs.k8s.io/controller-runtime (latest - verify at build), kubebuilder (latest - verify at build), tinygo (latest - verify board targets at build), wazero (latest - verify at build), and golangci-lint (latest - verify linter set at build).