How to Import Existing AWS Lambda Functions to Terraform

Sometimes, when working at a small scale or in a team that is new to the cloud, we can end up with Lambda resources that were provisioned manually through the AWS Management Console.
Although this isn’t necessarily an issue when the resources are small in number, it can quickly increase the maintenance overhead and force teams to plan for adopting an infrastructure as code approach instead.
In this article we’re going to look at how we can use Terraform to gain control over manually provisioned Lambda functions. The function itself will be a simple “Hello World!” function.
The article will not provide details on how to create or provision the function, but such details can easily be found online in a number of places, including here.
Overall, the aim of this article is to explain how to take existing manually provisioned Lambda functions and import them to Terraform.
The Problem
Let’s imagine that we are responsible for developing and maintaining various Lambda functions which happen to have been created manually.
What can complicate matters in this kind of scenario is the need to access source code as a zip file. Invariably this can lead to oversights where one particular dependency or file does not get properly bundled, leading to unexpected or unwanted performance side effects.
When we transition to infrastructure as code - Pulumi, Terraform, CDK or CloudFormation, for example - we can dramatically reduce the maintenance overhead because the source code of our functions can live in the place as their architectural configuration.
In the next section, we'll explore a simple example of how we can get over this kind of technical hurdle by moving resources to Terraform.
The Solution
Let’s walk through how we would import our “Hello World” Lambda function into Terraform.
First, let’s take a look at the function code, which for the purposes of this example is very simplistic:
exports.handler = async (event, context) => {
console.log(“Hello World!”);
return {
status: 200,
message: "Function was invoked successfully!"
};
}
Configure Terraform
The first thing we’ll need is a main.tf
file where we configure the Terraform provider:
# main.tf
provider "aws" {
region = "eu-west-1”
}
terraform {
backend "s3" {
bucket = “my-terraform-bucket"
key = "lambda-resources"
region = "eu-west-1”
}
}
All this main.tf
file does is configure the AWS account to be used for this infrastructure. In our example, we’re using the eu-west-1
region.
The backend
section of the file sets the storage, or backend, used for the Terraform state, which holds a record of the infrastructure’s current configuration. In this example, we’re using S3 as a backend.
Store Source Code
Now we need a place to store our Lambda source code. Let’s create a directory called src
with a subfolder in which we’ll put our code:
mkdir -p src/hello-world
touch index.js
Finally, we can simply paste the Lambda source code into the src/hello-world/index.js
file.
Import Lambda to Terraform
The final file we need is a Terraform file which will consist of three parts:
- An initial data block which allows us to pull in information about our Lambda function based on values we can find in the AWS Management Console
- A second data block which will be used for the zip file generated using the
src/hello-world/index.js
source code - A resource block which is where we can configure the Lambda function’s parameters. This block will be able to use values derived from the two data blocks described above
With these three things in mind, let’s take a look at the hello_world.tf
Terraform file in full.
Wow, this is quite a chunk of code to digest! Let’s step through it bit by bit below.
# hello_world.tf
# In this example, let’s assume the name of the manually provisioned function is “hello-world”
data "aws_lambda_function" “existing_hello_world_function” {
function_name = “hello-world”
}
data "archive_file" “hello_world_source_code” {
type = "zip"
output_path = "/tmp/hello_world_src_dir.zip"
source_dir = "src/hello-world”
}
resource "aws_lambda_function" “hello_world_function” {
function_name = data.aws_lambda_function.existing_hello_world_function.arn
description = “Outputs a simple ‘Hello World’ greeting to the console“
memory_size = 256
timeout = 30
role = data.aws_lambda_function.existing_hello_world_function.role
handler = "index.handler"
runtime = "nodejs20.x"
filename = data.archive_file.hello_world_source_code.output_path
source_code_hash = data.archive_file.hello_world_source_code.output_base64sha256
layers = []
tags = {}
# Putting a “FOO” environment variable here to demonstrate how the function environment can be customised
environment {
variables = {
“FOO” = “bar,
}
}
}
The first data block loads data on the existing “Hello World” function using its name, which we can find in the AWS Management Console. Note that we have added a local name of existing_hello_world_function to the existing function.
The second data block generates an archive from the src/hello-world
directory.
The resource block defines the configuration of our Terraform-managed Lambda function. Note that we are using some of the values derived from each of the data blocks in this section.
There are many more arguments that can be passed to the resource block above. See the relevant documentation for the full list of options.
Importing the Function
Although we have all the Terraform code ready to go, this is not quite enough to tick this task off our checklist. We still need to import
the resource, which can be done by issuing the following command:
terraform import aws_lambda_function.hello_world_function arn:aws:lambda:eu-west-1:<account-number>:function:hello-world
The first part of the command contains the local name of the aws_lambda_function resource from our hello_world.tf
file. The final part of the command contains the ARN of the Lambda function, which can easily be found in the Management Console.
After running the command, everything should be ready to go. If we make a very trivial change to the configuration then we can make sure of this.
Let’s change the timeout argument from 30 to 29 and see what happens when we run terraform plan
.
Note on Terraform Plan The
terraform plan
command creates an execution plan without actually carrying out that plan. More on the command can be found here.
As we expected, terraform plan
gives us the expected output, namely that the timeout parameter of the function will be changed but everything else remains the same.
Warning You may find that the source_code_hash value changes when running
terraform plan
for the first time, even though we didn’t change the source code itself. However, this is normal and will not affect the actual code that is executed for the Lambda function.
Conclusion
In this article, we took a look at a highly simplistic scenario in which we had a basic Lambda function which we needed to import to Terraform to give us greater control over maintenance and deployments.
We saw how, with the help of the terraform import
command, we can bring not only the Lambda’s source code under Terraform’s control, but also the function configuration.
This kind of approach lets us update event source mappings, allocated memory, timeouts, concurrency and source code in a single place, without needing to worry about zipping files or the monotony of "point and click" configuration activity.
Related Articles
Using AWS DMS to Depersonalise Sensitive Data
The AWS Database Migration Service is usually associated with the transfer…
September 12th, 2025
A CI/CD Pipeline using CodeBuild, RDS and Route53
CodePipeline is a managed product that can be used to create an automated…
August 9th, 2022
Easier Cron Jobs on AWS
Scheduling repetitive recurring tasks through code is a very common…
April 25th, 2022