Skip to main content

AWS Lambda Basics: Create and Run Serverless Functions

Tags:

Application development often comes with overhead beyond writing code — managing servers, automating startup and shutdown, and more. AWS Lambda is a serverless computing service that lets you focus purely on running your code, without thinking about server provisioning or management. Let's walk through the core Lambda concepts and how to create and invoke a function in practice.

What is AWS Lambda?

Lambda is a serverless computing service from AWS. You upload your code and the execution environment is automatically prepared — it scales in response to requests with no server management or capacity provisioning required.

You manage the code you want to run in units called "functions," and you can trigger them from a wide variety of events: HTTP requests, S3 file uploads, DynamoDB streams, and more. Since you're only charged for the time your code is actually running, Lambda is typically more cost-efficient than always-on servers.

Key Characteristics

Lambda has a few characteristics unique to the serverless model. It's worth understanding each one.

CharacteristicOverview
No server managementAWS handles OS patching and capacity management, so you can focus on writing code
Automatic scalingScales automatically with request volume, handling sudden traffic spikes
Pay-per-useBilled by execution duration (in 1 ms increments) and request count — no cost during idle time
Event-drivenTriggered by AWS services like S3, API Gateway, and DynamoDB, as well as custom events
Timeout limitMaximum execution time is 15 minutes — not ideal for long-running batch jobs

One thing to keep in mind is cold starts: a startup delay that occurs on first invocation or after a period of inactivity. Provisioned Concurrency lets you keep a specified number of execution environments pre-initialized and ready. For latency-sensitive use cases, enabling this feature eliminates cold starts.

Supported Runtimes

Lambda supports many programming language runtimes. If you need an unsupported language, you can bring your own custom runtime.

RuntimeSupported Versions (examples)
Python3.9 / 3.10 / 3.11 / 3.12 / 3.13
Node.js18.x / 20.x / 22.x
Java11 / 17 / 21
Go1.x (provided.al2023)
Ruby3.2 / 3.3
.NET8

Each runtime comes in two forms: AWS-managed runtimes (where AWS applies security patches) and custom runtimes (provided.al2023). Managed runtimes are deprecated when they reach end-of-life, so plan for periodic version upgrades.

Trying Lambda with the AWS CLI

Let's use the AWS CLI to create a Python Lambda function and invoke it. Functions need an IAM role with the permissions required to run, so we'll create the role first and then create the function.

Creating an IAM Role

Create the IAM role that the Lambda function will use at runtime. First, create a trust policy file that allows Lambda to assume the role.

cat << 'EOF' > trust-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF

Create the IAM role using the trust policy file:

❯ aws iam create-role \
--role-name exrecord-lambda-role \
--assume-role-policy-document file://trust-policy.json
{
"Role": {
"Path": "/",
"RoleName": "exrecord-lambda-role",
"RoleId": "AROA0a1b2c3d4e5f67890",
"Arn": "arn:aws:iam::123456789012:role/exrecord-lambda-role",
"CreateDate": "2026-04-18T04:00:35+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
}
}

Attach the AWSLambdaBasicExecutionRole managed policy, which allows the function to write logs to CloudWatch Logs:

❯ aws iam attach-role-policy \
--role-name exrecord-lambda-role \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Preparing the Function Code

Create a simple Python function and package it into a zip file.

cat << 'EOF' > lambda_function.py
def lambda_handler(event, context):
print("Hello from Lambda!")
return {
"statusCode": 200,
"body": "Hello, World!"
}
EOF

Compress the file into a zip:

zip function.zip lambda_function.py
adding: lambda_function.py (deflated 21%)

Creating the Function

Create the Lambda function by specifying the IAM role ARN and the zip file. The --handler flag takes the format filename.function_name to identify the entry point.

❯ aws lambda create-function \
--function-name exrecord-hello \
--runtime python3.12 \
--role arn:aws:iam::123456789012:role/exrecord-lambda-role \
--handler lambda_function.lambda_handler \
--zip-file fileb://function.zip
Output
{
"FunctionName": "exrecord-hello",
"FunctionArn": "arn:aws:lambda:us-east-1:123456789012:function:exrecord-hello",
"Runtime": "python3.12",
"Role": "arn:aws:iam::123456789012:role/exrecord-lambda-role",
"Handler": "lambda_function.lambda_handler",
"CodeSize": 302,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2026-04-18T04:01:54.411+0000",
"CodeSha256": "0a1b2c3d4e5f67890abcdef1234567890abcdef1234567890abcdef1234567890",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "0a1b2c3d-4e5f-6789-0abc-def123456789",
"State": "Pending",
"StateReason": "The function is being created.",
"StateReasonCode": "Creating",
"PackageType": "Zip",
"Architectures": [
"x86_64"
],
"EphemeralStorage": {
"Size": 512
},
"SnapStart": {
"ApplyOn": "None",
"OptimizationStatus": "Off"
},
"RuntimeVersionConfig": {
"RuntimeVersionArn": "arn:aws:lambda:us-east-1::runtime:0a1b2c3d4e5f67890"
},
"LoggingConfig": {
"LogFormat": "Text",
"LogGroup": "/aws/lambda/exrecord-hello"
}
}

Invoking the Function

Invoke the function from the AWS CLI. The response is written to the specified file.

❯ aws lambda invoke \
--function-name exrecord-hello \
--payload '{}' \
response.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}

Check the response:

cat response.json
{"statusCode": 200, "body": "Hello, World!"}

The function executed successfully and returned the expected response. Logs are recorded in the CloudWatch Logs group /aws/lambda/exrecord-hello.

Cleaning Up

Delete the function and role when you're done. Delete the function first, then detach the policy from the IAM role before deleting the role.

❯ aws lambda delete-function \
--function-name exrecord-hello
{
"StatusCode": 204
}

Detach the policy before deleting the role:

❯ aws iam detach-role-policy \
--role-name exrecord-lambda-role \
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Delete the role:

❯ aws iam delete-role \
--role-name exrecord-lambda-role

Summary

We covered the core concepts of AWS Lambda and how to create and invoke a function using the AWS CLI.

  • Lambda is a serverless computing service — no server provisioning or management required
  • It's event-driven and scales automatically with request volume
  • Pricing is based on execution duration and request count — no cost during idle time
  • Supports many runtimes including Python, Node.js, and Java, with custom runtime support as well
  • Functions need an IAM role with a trust policy, and AWSLambdaBasicExecutionRole is required to write logs to CloudWatch Logs