Hosting on AWS Lambda
AWS Lambda is a great way to host templ applications.
The example at https://github.com/a-h/templ/tree/main/examples/counter includes AWS CDK code for deploying onto AWS Lambda.
See the /cdk directory for the details.
Entrypoint
Lambda functions require an entrypoint that receives Lambda requests, and returns Lambda responses.
The https://github.com/akrylysov/algnhsa package provides an adaptor that allows the standard Go HTTP interface to be used.
package main
import (
"os"
"github.com/a-h/templ/examples/counter/db"
"github.com/a-h/templ/examples/counter/handlers"
"github.com/a-h/templ/examples/counter/services"
"github.com/a-h/templ/examples/counter/session"
"github.com/akrylysov/algnhsa"
"golang.org/x/exp/slog"
)
func main() {
// Create handlers.
log := slog.New(slog.NewJSONHandler(os.Stderr))
s, err := db.NewCountStore(os.Getenv("TABLE_NAME"), os.Getenv("AWS_REGION"))
if err != nil {
log.Error("failed to create store", slog.Any("error", err))
os.Exit(1)
}
cs := services.NewCount(log, s)
h := handlers.New(log, cs)
// Add session middleware.
sh := session.NewMiddleware(h)
// Start Lambda.
algnhsa.ListenAndServe(sh, nil)
}
Building and deploying
CDK provides the github.com/aws/aws-cdk-go/awscdklambdagoalpha/v2 package (aliased in this code as awslambdago) construct.
All that's required is to pass the path to the directory containing your Lambda function's main.go file and CDK will compile the code and deploy it.
// Strip the binary, and remove the deprecated Lambda SDK RPC code for performance.
// These options are not required, but make cold start faster.
bundlingOptions := &awslambdago.BundlingOptions{
GoBuildFlags: &[]*string{jsii.String(`-ldflags "-s -w" -tags lambda.norpc`)},
}
f := awslambdago.NewGoFunction(stack, jsii.String("handler"), &awslambdago.GoFunctionProps{
Runtime: awslambda.Runtime_PROVIDED_AL2(),
MemorySize: jsii.Number(1024),
Architecture: awslambda.Architecture_ARM_64(),
Entry: jsii.String("../lambda"),
Bundling: bundlingOptions,
Environment: &map[string]*string{
"TABLE_NAME": db.TableName(),
},
})
// Add a Function URL.
lambdaURL := f.AddFunctionUrl(&awslambda.FunctionUrlOptions{
AuthType: awslambda.FunctionUrlAuthType_NONE,
})
awscdk.NewCfnOutput(stack, jsii.String("lambdaFunctionUrl"), &awscdk.CfnOutputProps{
ExportName: jsii.String("lambdaFunctionUrl"),
Value: lambdaURL.Url(),
})
Static content
To serve static content such as images alongside Lambda functions that serve HTML or REST API responses, a common pattern is to use a CloudFront distribution that routes traffic to S3 or to the Lambda Function URL, based on the URL structure.
The example CDK stack includes a deployment process that updates the contents of the S3 bucket.
Deployed example
To see the deployed sample application running on AWS Lambda, visit https://d3qfg6xxljj3ky.cloudfront.net