100 millions Lambda execution and guess our AWS $$$ Bill - GoLang

Search for a command to run...

Damn, that's one hell of an optimization job!! How many users are you supporting with 98M requests/month?
Use Case:- I am sure you all remember how much boilerplate code we used to write when we convert the DynamoDB stream to the business object. Here is a small snippet of the GoLang program. m := &EntitySearch{} for name, value := range recordI...

Use Case:- Our company has an SFTP server in the lower environment, but we don't have regular traffic on it. Our QA team only uses it once every two weeks during production release testing. If you create an AWS SFTP server, you will be charged $0.30 ...

Use Case:- We have a business use case where we need to call our nightly job for multiple tenants. Initially, I planned to use EventBridge Bus and Rules to achieve this goal. However, we discovered that EventBridge Rules has a limit of 5 targets, whi...

As I mentioned in my prior post, we used the ECS Fargate instance in my organization. During off hours, we shut down the ECS Fargate instance every day in our lower environment to cut costs. Here is a prior article where I have explained about Start/...

Little Background:-
in 2019 we started moving from server to serverless and started adopting AWS Lambda + GoLang for any new development. My chief architect and current CTO Ben Pyle(Blog) came up with the GoLang pattern which we used in all our Microservices. It was one of the best architectural decisions we have made in recent times.
As of now, we have more than 300+ lambdas deployed in each of our environments. 99% of those lambdas are written in GoLang and the rest 1% in either Node, Python or Java. Most of us had a Java background in my organization when we started in 2019. A couple of GoLang training sessions have helped us in a smooth transition.
This post will help you to understand and implement AWS Lambda written in GoLang.
AWS Bill:-
Here is a screenshot of our recent month's bill. You can see we had 98+ million lambda requests and our total AWS bill for lambda was $108 after our compute savings plan.

Keep 3 things in mind when you write Lambda. 1) Runtime 2) Package Size 3) Startup logic.
The majority of the Go Lambda that we have in my organization is configured with 128 MB memory (that's the minimum memory we can configure for AWS Lambda).
Go executable binary size is approx 8 MB for most of our Lambda. Fewer footprints for runtime.
Here are a couple of runtime examples. You can see the COLD START time in this example is 210.65 ms and it used 45 MB of memory. As GoLang compiles code to native code and executes pretty fast, most of the time cold start duration will be a few milliseconds to 1 second.
Duration: 3.93 ms Billed Duration: 4 ms Memory Size:
128 MB Max Memory Used: 44 MB Init Duration: 210.65 ms
Duration: 1.36 ms Billed Duration: 2 ms Memory Size:
128 MB Max Memory Used: 45 MB
Duration: 16.44 ms Billed Duration: 17 ms Memory Size:
128 MB Max Memory Used: 45 MB
Examples:-
We follow industry best practices for implementing AWS Lambda.
Optimizing static initialization:- This is the "INIT" code that happens outside of the handler. Initialized your variable or connection to other services.
Single-purpose lambdas:- each lambda has a single responsibility. For any CRUD operation, we implement 4 lambdas (Create, Update, Delete and Get)
This example is implemented using AWS CDK and AWS SAM, whichever is your preferred way, clone the repo from GitHub and try it...
You can download the source code from here
AWS SAM Deployment Instructions:-
Region:
Type: String
Description: AWS Region Name
Default: us-west-2
cd sam
sam deploy --stack-name employee-functions --capabilities CAPABILITY_NAMED_IAM --guided --profile <your profile name>
Key APIEndpoint
Description endpoint of EmployeeApi
Value https://fy6fpson09.execute-api.us-west-2.amazonaws.com/
AWS CDK Deployment Instructions:-
export const getConfig = (): Options => {
return {
defaultRegion: "us-west-2",
apiStageName: "main",
}
}
cd cdk
cdk deploy --all -a "npx ts-node bin/app.ts" --profile <your profile name>
aws cloudformation list-exports --query "Exports[?Name=='employee-api-url'].Value" --output text --profile <your profile name>
API Execution:-
curl -X POST -H 'Content-type: application/json'
https://fy6fpson09.execute-api.us-west-2.amazonaws.com/main/employee \
--data '{
"Age": 30,
"FirstName": "Kyle",
"LastName" : "Gray"
}'
You will see the following record in DynamoDB.

curl -X GET -H 'Content-type: application/json' https://fy6fpson09.execute-api.us-west-2.amazonaws.com/main/employee/2414 | jq
Response:-
{
"Id": 2414,
"firstName": "Kyle",
"lastName": "Gray",
"age": 30,
"createdDatetime": "2023-03-06T05:23:59.471574185Z",
"modifiedDatetime": "0001-01-01T00:00:00Z"
}
curl -X PUT -H 'Content-type: application/json' https://fy6fpson09.execute-api.us-west-2.amazonaws.com/main/employee/2414
--data '{
"Age": 31,
"FirstName": "Kyle",
"LastName" : "Gray"
}'
Updated record in DynamoDB

curl -X DELETE -H 'Content-type: application/json' https://fy6fpson09.execute-api.us-west-2.amazonaws.com/main/employee/2414
Cleanup:-
sam delete --stack-name employee-functions --profile <your profile name>
OR
cdk destroy --profile <your profile name>
Wrap-Up:-
As you can see how it's easy to understand, implement and deploy GoLang lambda in an AWS environment. I would highly recommend trying it yourself and for your organization. We have a couple of legacy applications where we use an ECS container with 1 CPU and 2 GB RAM, this cost us around $32 per month. Even though the traffic pattern is not consistent, we end up paying $32 per month. In the case of serverless, we pay per use and don't pay anything when there is no traffic. In the next post, I will implement the same example with low code or less code using Step Function + universal target.