AWS Lambda Basics: Create and Run Serverless Functions
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.
What is AWS Lambda? - AWS Lambda
Lambda is a compute service that you can use to build applications without provisioning or managing ...
Key Characteristics
Lambda has a few characteristics unique to the serverless model. It's worth understanding each one.
| Characteristic | Overview |
|---|---|
| No server management | AWS handles OS patching and capacity management, so you can focus on writing code |
| Automatic scaling | Scales automatically with request volume, handling sudden traffic spikes |
| Pay-per-use | Billed by execution duration (in 1 ms increments) and request count — no cost during idle time |
| Event-driven | Triggered by AWS services like S3, API Gateway, and DynamoDB, as well as custom events |
| Timeout limit | Maximum 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.
Configuring provisioned concurrency for a function - AWS Lambda
This topic details how to manage and configure provisioned concurrency. For a conceptual overview of...
Supported Runtimes
Lambda supports many programming language runtimes. If you need an unsupported language, you can bring your own custom runtime.
| Runtime | Supported Versions (examples) |
|---|---|
| Python | 3.9 / 3.10 / 3.11 / 3.12 / 3.13 |
| Node.js | 18.x / 20.x / 22.x |
| Java | 11 / 17 / 21 |
| Go | 1.x (provided.al2023) |
| Ruby | 3.2 / 3.3 |
| .NET | 8 |
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.
Lambda runtimes - AWS Lambda
Learn about the languages that Lambda supports through runtimes.
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
AWSLambdaBasicExecutionRoleis required to write logs to CloudWatch Logs