Background

While researching how to run a Go web application on AWS Lambda, I came across a technology called the AWS Lambda Web Adapter.

The AWS Lambda Web Adapter allows web applications built with various frameworks (e.g., Express.js, Flask, Laravel, Next.js, etc.) to run on Lambda.

https://github.com/awslabs/aws-lambda-web-adapter?tab=readme-ov-file#examples

It’s reasonable to assume that web application frameworks not listed in the official examples, such as Ruby on Rails, can also be run on Lambda.

In this case, I used the AWS Lambda Web Adapter and SAM (Serverless Application Model) to deploy a simple server application built with the Go web framework Echo via Lambda Function URLs.

The code I created is publicly available as a template repository on GitHub:

https://github.com/ryichk/go-echo-lambda-function-url-template

While researching, I found samples using Gin in the official AWS Lambda Web Adapter examples and a Zenn article with a Fiber sample. However, I couldn’t find any samples using Echo, so I decided to publish this article.

https://github.com/awslabs/aws-lambda-web-adapter/tree/main/examples/gin

Steps and Explanation

1. Building the Echo Server

Build a web application using Echo. For this example, I created a simple app that displays Hello! when accessing localhost:8000/.

package main

import (
    "net/http"

    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func main() {
    e := echo.New()
    e.GET("/", hello)
    e.Logger.Fatal(e.Start(":8000"))
}

func hello(c echo.Context) error {
    return c.String(http.StatusOK, "Hello!")
}

2. Creating the Dockerfile

The Dockerfile was based on the Gin Dockerfile from the official Lambda Web Adapter examples.

FROM golang:1.24-alpine AS build_base
RUN apk add --no-cache git
WORKDIR /app

COPY . .
RUN go mod download

RUN GOOS=linux CGO_ENABLED=0 go build -o bootstrap ./app
FROM alpine:3.9
RUN apk add ca-certificates

# Only this line is needed to use the Lambda Web Adapter in the Docker image
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.4 /lambda-adapter /opt/extensions/lambda-adapter
COPY --from=build_base /app/bootstrap /app/bootstrap

ENV PORT=8000 AWS_LWA_ASYNC_INIT=true
EXPOSE 8000

CMD ["/app/bootstrap"]

By default, the Lambda Web Adapter assumes the web app listens on port 8080. To use a different port, specify it using the PORT or AWS_LWA_PORT environment variable.

However, in the Lambda execution environment, the web app runs as a non-root user, so it cannot listen on port numbers below 1024. Additionally, it’s best to avoid ports 3000 (used by CloudWatch Lambda Insight extension) and 9001 (used by the Lambda Runtime API).

Reference: https://github.com/awslabs/aws-lambda-web-adapter?tab=readme-ov-file#configurations:~:text=AWS_LWA_PORT%20/%20PORT%20%2D%20Lambda,uses%20port%203000.

The following environment variable is optional:

AWS_LWA_ASYNC_INIT=true

If a Lambda function doesn’t complete initialization within 10 seconds, Lambda restarts the function and charges for initialization. The Lambda Web Adapter supports asynchronous initialization to avoid restarts by utilizing the 10-second initialization window. When enabled, it performs readiness checks for up to 9.8 seconds. If the web app isn’t ready, it notifies the Lambda service of initialization completion and continues readiness checks in the handler. This feature is disabled by default but can be enabled by setting AWS_LWA_ASYNC_INIT or ASYNC_INIT to true.

Reference: https://github.com/awslabs/aws-lambda-web-adapter?tab=readme-ov-file#configurations:~:text=AWS_LWA_ASYNC_INIT%20/%20ASYNC_INIT%20%2D%20Lambda,to%20true.

3. Creating the SAM template.yaml

For Lambda Function URLs, I referenced the template.yaml for nextjs-response-streaming from the official examples.

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Go's Echo Web application.

Globals:
  Function:
    Timeout: 5
    MemorySize: 128

Resources:
  GoEchoAppFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: app/
      PackageType: Image
      Architectures:
      - x86_64
      FunctionUrlConfig:
        AuthType: NONE
    Metadata:
      DockerTag: v1
      DockerContext: .
      Dockerfile: Dockerfile

Outputs:
  GoEchoAppFunctionOutput:
    Description: "Go's Echo App Function ARN"
    Value: !GetAtt GoEchoAppFunction.Arn
  GoEchoAppFunctionUrlOutput:
    Description: "Go's Echo App Function URL"
    Value: !GetAtt GoEchoAppFunctionUrl.FunctionUrl

Setting AuthType to NONE in FunctionUrlConfig makes the URL publicly accessible.

5. Building with SAM CLI

$ sam build
Building codeuri: /Pathto/go-echo-lambda-function-url-template runtime: None architecture: x86_64 functions: GoEchoAppFunction
Building image for GoEchoAppFunction function
Setting DockerBuildArgs for GoEchoAppFunction function
Step 1/13 : FROM golang:1.24-alpine AS build_base

~ Omitted ~

Successfully tagged goechoappfunction:v1

Build Succeeded

Built Artifacts  : .aws-sam/build
Built Template   : .aws-sam/build/template.yaml

6. Deploying with SAM CLI

$ sam deploy

~ Omitted ~

Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

2024-08-24 21:45:24 - Waiting for stack create/update to complete

CloudFormation events from stack operations (refresh every 5.0 seconds)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                                                 ResourceType                                                   LogicalResourceId                                              ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
UPDATE_IN_PROGRESS                                             AWS::CloudFormation::Stack                                     go-echo-app                                                    User Initiated
UPDATE_IN_PROGRESS                                             AWS::Lambda::Function                                          GoEchoAppFunction                                              -
UPDATE_COMPLETE                                                AWS::Lambda::Function                                          GoEchoAppFunction                                              -
UPDATE_COMPLETE_CLEANUP_IN_PROGRESS                            AWS::CloudFormation::Stack                                     go-echo-app                                                    -
UPDATE_COMPLETE                                                AWS::CloudFormation::Stack                                     go-echo-app                                                    -
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key                 GoEchoAppFunctionUrlOutput
Description         Go's Echo App Function URL
Value               https://xxx.lambda-url.ap-northeast-1.on.aws/

Key                 GoEchoAppFunctionOutput
Description         Go's Echo App Function ARN
Value               arn:aws:lambda:ap-northeast-1:000000000000:function:go-echo-app-GoEchoAppFunction-XXXXXXXX
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - go-echo-app in ap-northeast-1

7. Verification

$ curl https://xxx.lambda-url.ap-northeast-1.on.aws/
Hello!%

8. Deleting Resources

$ sam delete

Additional References