Deploy AWS serverless API with Go and Terraform
In the tutorial, we will explore how to deploy a simple API in a serverless manner using Go, Terraform, AWS API Gateway, and AWS Lambda. We will create an API Gateway and integrate it with our Lambda function, use Terraform to define our infrastructure as code and automate the deployment process.
Overview
In the previous article "Deploy Go AWS lambda function using Terraform", we explored how to deploy a simple AWS Lambda function written in Go using Terraform. We learned how to define our infrastructure as code and automate the deployment process, making it easy to reproduce our setup and scale our application.
In this article, we will build on that foundation and extend our application by adding an API Gateway to expose our Lambda function to the world. We will continue to use Terraform to define our infrastructure as code and automate the deployment process, but this time we will also use AWS API Gateway to create a RESTful API that can be used to invoke our Lambda function.
By the end of this tutorial, you will have a fully functional API that can be used to interact with your Lambda function and a repeatable deployment process that makes it easy to update and scale your infrastructure. So let's get started and learn how to deploy a simple API using Go, Terraform, AWS API Gateway, and AWS Lambda.
All the code can be found in the tutorial GitHub repo.
If you don't want to miss similar articles and stay up to date on our latest content, subscribe to the newsletter 📩 and never miss an update!
Go lambda function
First, let's write a code for our lambda function.
The main change that we provide to the function is a response type. API Gateway does the transformation of HTTP requests into the input event for lambda and receives the response from lambda also as a response event to convert them into HTTP response. These event types are implemented in a github.com/aws/aws-lambda-go/events
package, that we use.
Final project structure
The project structure for our project will look like this:
tutorial/
|-- lambda/
| `-- hello-world/
| `-- main.go
|-- api_gateway.tf
|-- iam.tf
|-- lambda.tf
|-- locals.tf
`-- main.tf
As we can see, the only difference with the previous guide is api_gateway.tf
file, where we will have all the API Gateway resources.
Create AWS resources
To set up API Gateway for your lambda function we need to use the code for lambda resource from the previous tutorial. We are going to deploy our hello-world
function with the new resource naming for convenience:
Create API Gateway
To create API Gateway we need to use resource aws_apigatewayv2_api
:
Here we provide a basic cors policy, protocol, name, and description.
Note: For tutorial purpose, we provided a "*" as allow_origin
policy value, that should be avoided on production environment. We should specify a list of particular resources, from where we expect the request.
Additionally, we need to specify the stage for the API gateway. Stages are a way to manage and deploy multiple versions of your API for AWS API Gateway. For example, you may have a prod
stage for your live production environment and a dev
stage for development and testing. We are going to create one stage golang
for the tutorial:
Finally, we need logs for our gateway:
Create API Gateway lambda integration
To allow API Gateway to invoke lambda when an HTTP request is made, we need to create an API Gateway integration, that can be a Lambda function, an HTTP webpage, or an AWS service action. In our case, we are going to create lambda integration:
Here we specify the type of lambda integration as AWS_PROXY
. This type of integration provides seamless integration for direct lambda invocation by API Gateway providing all necessary HTTP request fields as lambda events. Other integration types, like AWS
, HTTP
, MOCK
, HTTP_PROXY
, with detailed explanations, can be found in the official docs.
To specify when the lambda should be triggered, we need to create an API Gateway route:
This set up our lambda to be triggered for GET requests with /api/v1/hello
path.
We also need to provide permission for the gateway to invoke the lambda function:
The last thing we should add for simplicity is output with created API URL:
It will help to get the API endpoint for the newly created API gateway, so we can make requests to it for testing.
Let's deploy
As usual, we are going to plan the resources first:
terraform init
terraform plan
We should see:
...
Plan: 12 to add, 0 to change, 0 to destroy.
Looks correct, so let's deploy it using
terraform apply
and typing yes
.
After the deployment is completed we should see the result and our output api_url
:
Apply complete! Resources: 12 added, 0 changed, 0 destroyed.
Outputs:
api_url = "https://bwtdt0lujk.execute-api.us-east-1.amazonaws.com"
binary_path = "./tf_generated/hello-world"
You should have your own api_url
subdomain, as AWS generates it uniquely.
Validate that Go API works
To validate the deployment we should make a get request to the endpoint api_url
and specify the path to our lambda function integration. API Gateway builds the path as "${api_url}/${stage}/${route}"
so in our case we should make a request to https://bwtdt0lujk.execute-api.us-east-1.amazonaws.com/golang/api/v1/hello
. As it is a GET
request we can just go to the URL in the browser and see the response:
You are awesome :)
Destroy resources
To destroy all the resources we created we need to run:
terraform destroy
and click yes
.
Conclusion
In conclusion, we have seen how to deploy a simple API using Go, Terraform, AWS API Gateway, and AWS Lambda. By using these powerful tools, we can create a reliable and scalable infrastructure that can handle a large number of requests.
Hope this tutorial has been helpful in demonstrating the power of Terraform and AWS to automate the deployment process and create a fully functional API on AWS.
If you enjoyed this article and want to stay up to date on our latest content, subscribe to the newsletter 📩 and never miss an update!
Thank you for reading and happy coding 💻