Last week AWS published a blog post advising that the
runtime will be deprecated and people should migrate to
provided.al2. I was
already using the newer runtime, but I also learned from the blog post that AWS
SAM can now build Go Lambda functions for the newer runtime - no more Makefiles
I switched from
BuildMethod: makefile to
BuildMethod: go1.x and noticed that
my Lambda packages were now twice the size. This means slower cold starts and
slower deployments - especially from my laptop in Australia. I also noticed that
my CI pipelines were slower because every commit was causing Lambda updates, even
when no code had changed.
The cause of all these issues was the set of build-time flags. My Makefile was setting them, but the AWS SAM builder defaults to no flags. The problem can be addressed by setting the following environment variable while building (i.e. in your CI system):
export GOFLAGS="-buildvcs=false -trimpath '-ldflags=-s -w -buildid='"
Setting this environment variable halved the size of my Lambda packages and caused update churn to go away, meaning faster CI. Breaking down the flags:
Three of the flags relate to deterministic builds.
-buildvcs=false causes Go
to not embed the Git commit hash and date in the built binaries. This can be
useful for distributed tools, but causes every commit to generate unique Lambda
package ZIPs - not what I wanted. The linker flag
-buildid= is the same: it
tells Go not to embed a unique hash in the binary.
-trimpath is similar: it
tells Go not to embed the absolute paths of packages in the binary. This means
deploying from my laptop (where the code lives under
and from CI (where it could be anything!) will produce the same binaries.
The other two flags relate to binary size. The
-s linker flag causes the Go
linker to omit the symbol table from the binary. Note that this does not
affect stacktraces. If your function panics, you still get a full stack trace
with function names and line numbers. The
-w linker flag causes the Go linker
to omit DWARF data from the binary. This means the binary can’t (usefully) be
controlled by a debugger, but that’s not relevant in the Lambda environment.