Creating and Deploying a Lambda Function
Lambda functions can be created and deployed using the management console or the AWS CLI. With the CLI, you use aws lambda create-function to upload a ZIP package and create a function, and aws lambda update-function-code to update the code. Container image deployment using --package-type Image is also supported, and is useful when you have many dependencies or a package exceeding 250 MB.
Syntax
# -----------------------------------------------
# Create a ZIP package
# -----------------------------------------------
# zip {output-file} {target-files...}
# → Creates a ZIP package to upload to Lambda
# Example: zip function.zip index.py
# zip -r {output-file} {target-directory}
# → Compresses an entire directory into a ZIP (use when including dependencies)
# Example: zip -r function.zip . -x "*.git*"
# -----------------------------------------------
# Create a Lambda function (ZIP deployment)
# -----------------------------------------------
# aws lambda create-function \
# --function-name {function-name} \
# --runtime {runtime} \
# --role {execution-role-ARN} \
# --handler {handler} \
# --zip-file fileb://{zip-file}
# → Creates a new Lambda function by uploading a ZIP package
# Example: aws lambda create-function \
# --function-name okabe-time-leap \
# --runtime python3.12 \
# --role arn:aws:iam::111122223333:role/lambda-execution-role \
# --handler index.handler \
# --zip-file fileb://function.zip
# aws lambda create-function \
# --function-name {function-name} \
# --runtime {runtime} \
# --role {execution-role-ARN} \
# --handler {handler} \
# --zip-file fileb://{zip-file} \
# --memory-size {memory-MB} \
# --timeout {timeout-seconds} \
# --environment Variables="{KEY=VALUE,...}"
# → Creates a function with memory, timeout, and environment variables specified
# Example: aws lambda create-function \
# --function-name kurisu-divergence-calc \
# --runtime python3.12 \
# --role arn:aws:iam::111122223333:role/lambda-execution-role \
# --handler calc.handler \
# --zip-file fileb://function.zip \
# --memory-size 512 \
# --timeout 30 \
# --environment 'Variables={DIVERGENCE_THRESHOLD=1.048596,LOG_LEVEL=INFO}'
# -----------------------------------------------
# Update function code
# -----------------------------------------------
# aws lambda update-function-code \
# --function-name {function-name} \
# --zip-file fileb://{zip-file}
# → Overwrites the code of an existing Lambda function with a ZIP file
# Example: aws lambda update-function-code \
# --function-name okabe-time-leap \
# --zip-file fileb://function.zip
# -----------------------------------------------
# Container image deployment
# -----------------------------------------------
# aws lambda create-function \
# --function-name {function-name} \
# --package-type Image \
# --code ImageUri={ECR-image-URI} \
# --role {execution-role-ARN}
# → Creates a Lambda function using a container image
# Example: aws lambda create-function \
# --function-name mayuri-mail-sender \
# --package-type Image \
# --code ImageUri=111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/mayuri-app:latest \
# --role arn:aws:iam::111122223333:role/lambda-execution-role
Reference
| Command / Operation | Description |
|---|---|
zip function.zip index.py | Compresses a single file into a ZIP. Used to create the package to upload to Lambda. |
zip -r function.zip . -x "*.git*" | Compresses the entire current directory (including dependencies) into a ZIP. Use -x to exclude unnecessary files. |
aws lambda create-function | Creates a new Lambda function. --runtime, --role, --handler, and --zip-file are required options. |
--runtime {runtime} | Specifies the execution environment for the function. Options include python3.12, nodejs20.x, java21, and go1.x. |
--role {ARN} | Specifies the ARN of the IAM execution role assigned to the function. At minimum, write access to CloudWatch Logs is required. See Creating and Assigning IAM Roles for details. |
--handler {filename.function_name} | Specifies the entry point Lambda invokes. For Python, use index.handler; for Node.js, use index.handler as well. |
--zip-file fileb://{path} | Specifies the path to the ZIP file to upload. The fileb:// prefix transfers the file as binary. |
--memory-size {MB} | Specifies the memory to allocate to the function in MB. Values range from 128 to 10,240, and CPU performance scales proportionally. |
--timeout {seconds} | Specifies the maximum execution time in seconds. Values range from 1 to 900; the default is 3 seconds. |
--environment Variables={...} | Sets environment variables for the function as key-value pairs. Used to externalize DB connection strings and API keys. |
aws lambda update-function-code --zip-file ... | Updates the code of an existing Lambda function using a ZIP file. Configuration (memory, timeout, etc.) is not changed. |
--package-type Image | Specifies container image deployment for the Lambda function. Use --code ImageUri to specify the ECR image URI. |
| Deployment Method | Description |
|---|---|
| ZIP deployment (direct upload) | Packages under 50 MB can be uploaded directly via the CLI or management console. Suitable for lightweight functions. |
| ZIP deployment (via S3) | For packages over 50 MB, upload to S3 first, then reference the location using --s3-bucket and --s3-key. Supports up to 250 MB (unzipped). |
| Container image deployment | Build a container image with a Dockerfile, push it to ECR, and specify its URI in Lambda. Supports up to 10 GB, making it suitable for large dependencies such as machine learning models. |
Sample Code
# -----------------------------------------------
# Create a Lambda function that counts time leaps
# using Steins;Gate characters as sample data
# First, prepare the code and compress it into a ZIP
# -----------------------------------------------
# Create a working directory
mkdir okabe-time-leap && cd okabe-time-leap
# Create the Lambda function code (index.py)
cat > index.py << 'EOF'
import json
# Handler function that counts time leaps
def handler(event, context):
# Get the operator from the event (default: Okabe)
operator = event.get('operator', 'Okabe')
# Get the divergence meter value
divergence = event.get('divergence', 1.048596)
# Build the response
response = {
'statusCode': 200,
'body': json.dumps({
'operator': operator,
'divergence': divergence,
'message': f'{operator} performed a time leap to divergence {divergence}%!'
})
}
return response
EOF
# Compress the single file into a ZIP
zip function.zip index.py
# Verify the contents of the ZIP
unzip -l function.zip
$ mkdir okabe-time-leap && cd okabe-time-leap
$ zip function.zip index.py
adding: index.py (deflated 38%)
$ unzip -l function.zip
Archive: function.zip
Length Date Time Name
--------- ---------- ----- ----
412 2026-03-26 10:00 index.py
--------- -------
412 1 file
# -----------------------------------------------
# Create the okabe-time-leap function in the Tokyo region
# Uses an IAM execution role created in advance
# -----------------------------------------------
# Create the Lambda function
aws lambda create-function \
--function-name okabe-time-leap \
--runtime python3.12 \
--role arn:aws:iam::111122223333:role/lambda-basic-execution-role \
--handler index.handler \
--zip-file fileb://function.zip \
--memory-size 256 \
--timeout 30 \
--environment 'Variables={OPERATOR_NAME=Okabe,DIVERGENCE_THRESHOLD=1.048596}' \
--region ap-northeast-1
# Check the configuration of the created function
aws lambda get-function-configuration \
--function-name okabe-time-leap \
--region ap-northeast-1 \
--query '{Name:FunctionName,Runtime:Runtime,Memory:MemorySize,Timeout:Timeout,State:State}'
$ aws lambda create-function \
> --function-name okabe-time-leap \
> --runtime python3.12 \
> --role arn:aws:iam::111122223333:role/lambda-basic-execution-role \
> --handler index.handler \
> --zip-file fileb://function.zip \
> --memory-size 256 \
> --timeout 30 \
> --environment 'Variables={OPERATOR_NAME=Okabe,DIVERGENCE_THRESHOLD=1.048596}' \
> --region ap-northeast-1
{
"FunctionName": "okabe-time-leap",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:111122223333:function:okabe-time-leap",
"Runtime": "python3.12",
"Role": "arn:aws:iam::111122223333:role/lambda-basic-execution-role",
"Handler": "index.handler",
"CodeSize": 412,
"MemorySize": 256,
"Timeout": 30,
"State": "Pending",
"LastModified": "2026-03-26T10:05:00.000+0000"
}
$ aws lambda get-function-configuration \
> --function-name okabe-time-leap \
> --region ap-northeast-1 \
> --query '{Name:FunctionName,Runtime:Runtime,Memory:MemorySize,Timeout:Timeout,State:State}'
{
"Name": "okabe-time-leap",
"Runtime": "python3.12",
"Memory": 256,
"Timeout": 30,
"State": "Active"
}
# -----------------------------------------------
# Add the requests library to Kurisu's divergence
# calculation function and update the code
# Install dependencies locally with pip install
# -----------------------------------------------
# Create a working directory
mkdir kurisu-divergence-calc && cd kurisu-divergence-calc
# Install dependencies into the current directory
pip install requests -t .
# Create the function code (calc.py)
cat > calc.py << 'EOF'
import json
import requests
# Handler for divergence value calculation
def handler(event, context):
# Get the list of divergence candidates from the event
candidates = event.get('candidates', [])
# Filter candidates in the 1% range (Steins;Gate world line)
steins_gate_candidates = [
v for v in candidates
if 1.0 <= v < 2.0
]
return {
'statusCode': 200,
'body': json.dumps({
'researcher': 'Kurisu',
'steins_gate_candidates': steins_gate_candidates,
'count': len(steins_gate_candidates)
})
}
EOF
# Compress the entire directory into a ZIP (excluding .git)
zip -r function.zip . -x "*.git*" -x "__pycache__/*" -x "*.pyc"
# Update the existing Lambda function code
aws lambda update-function-code \
--function-name kurisu-divergence-calc \
--zip-file fileb://function.zip \
--region ap-northeast-1
$ pip install requests -t .
Collecting requests
Downloading requests-2.31.0-py3-none-any.whl (62 kB)
...
Successfully installed certifi-2024.2.2 charset-normalizer-3.3.2 idna-3.6 requests-2.31.0 urllib3-2.2.1
$ zip -r function.zip . -x "*.git*" -x "__pycache__/*" -x "*.pyc"
adding: calc.py (deflated 42%)
adding: requests/ (stored 0%)
adding: requests/__init__.py (deflated 55%)
...
$ aws lambda update-function-code \
> --function-name kurisu-divergence-calc \
> --zip-file fileb://function.zip \
> --region ap-northeast-1
{
"FunctionName": "kurisu-divergence-calc",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:111122223333:function:kurisu-divergence-calc",
"Runtime": "python3.12",
"CodeSize": 284731,
"LastModified": "2026-03-26T10:20:00.000+0000",
"State": "Active",
"LastUpdateStatus": "Successful"
}
# -----------------------------------------------
# Steps to create a function in the management
# console (using Mayuri's notification function as an example)
# -----------------------------------------------
# 1. Sign in to the AWS Management Console
# → https://console.aws.amazon.com/
# 2. Open the Lambda service and click "Create function"
# 3. Fill in the following fields:
# - Function name: mayuri-mail-notification
# - Runtime: Python 3.12
# - Architecture: x86_64 (or arm64)
# - Execution role: Use an existing role or create a new one with basic Lambda permissions
# 4. Click "Create function"
# 5. Enter your code in the inline editor and click "Deploy"
# 6. Create a test event on the "Test" tab to verify the function
# Example test event JSON:
# {
# "recipient": "mayuri@future-gadget-lab.jp",
# "message": "Tutturu! New D-mail received!"
# }
# Test-invoke the function created via CLI
aws lambda invoke \
--function-name mayuri-mail-notification \
--cli-binary-format raw-in-base64-out \
--payload '{"recipient":"mayuri@future-gadget-lab.jp","message":"Tutturu! New D-mail received!"}' \
--region ap-northeast-1 \
response.json
cat response.json
$ aws lambda invoke \
> --function-name mayuri-mail-notification \
> --cli-binary-format raw-in-base64-out \
> --payload '{"recipient":"mayuri@future-gadget-lab.jp","message":"Tutturu! New D-mail received!"}' \
> --region ap-northeast-1 \
> response.json
{
"StatusCode": 200,
"ExecutedVersion": "$LATEST"
}
$ cat response.json
{"statusCode": 200, "body": "{\"sent\": true, \"recipient\": \"mayuri@future-gadget-lab.jp\"}"}
# -----------------------------------------------
# Deploy Daru's machine learning model to Lambda
# using a container image
# Container image deployment is effective when you
# have large dependencies such as PyTorch
# -----------------------------------------------
# Create a Dockerfile
cat > Dockerfile << 'EOF'
# Use the AWS-provided Python 3.12 Lambda base image
FROM public.ecr.aws/lambda/python:3.12
# Install dependencies for Daru's model
COPY requirements.txt .
RUN pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
# Copy the function code
COPY daru_predictor.py ${LAMBDA_TASK_ROOT}
# Specify the handler
CMD ["daru_predictor.handler"]
EOF
# Build the container image
docker build -t daru-predictor .
# Log in to ECR
aws ecr get-login-password --region ap-northeast-1 \
| docker login --username AWS \
--password-stdin 111122223333.dkr.ecr.ap-northeast-1.amazonaws.com
# Create an ECR repository (first time only)
aws ecr create-repository \
--repository-name daru-predictor \
--region ap-northeast-1
# Tag the image for ECR
docker tag daru-predictor:latest \
111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/daru-predictor:latest
# Push to ECR
docker push \
111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/daru-predictor:latest
# Create the Lambda function using the container image
aws lambda create-function \
--function-name daru-predictor \
--package-type Image \
--code ImageUri=111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/daru-predictor:latest \
--role arn:aws:iam::111122223333:role/lambda-basic-execution-role \
--memory-size 3008 \
--timeout 120 \
--region ap-northeast-1
$ docker build -t daru-predictor .
[+] Building 45.2s (8/8) FINISHED
$ aws ecr get-login-password --region ap-northeast-1 \
> | docker login --username AWS \
> --password-stdin 111122223333.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded
$ aws ecr create-repository \
> --repository-name daru-predictor \
> --region ap-northeast-1
{
"repository": {
"repositoryArn": "arn:aws:ecr:ap-northeast-1:111122223333:repository/daru-predictor",
"registryId": "111122223333",
"repositoryName": "daru-predictor",
"repositoryUri": "111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/daru-predictor"
}
}
$ docker push 111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/daru-predictor:latest
latest: digest: sha256:a1b2c3d4e5f6... size: 3284
$ aws lambda create-function \
> --function-name daru-predictor \
> --package-type Image \
> --code ImageUri=111122223333.dkr.ecr.ap-northeast-1.amazonaws.com/daru-predictor:latest \
> --role arn:aws:iam::111122223333:role/lambda-basic-execution-role \
> --memory-size 3008 \
> --timeout 120 \
> --region ap-northeast-1
{
"FunctionName": "daru-predictor",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:111122223333:function:daru-predictor",
"PackageType": "Image",
"MemorySize": 3008,
"Timeout": 120,
"State": "Pending",
"LastModified": "2026-03-26T10:45:00.000+0000"
}
# ----------------------------------------------- # For ZIPs over 50 MB, deploy via S3 # Using Moeka's large-scale data processing function as an example # ----------------------------------------------- # Upload the ZIP to an S3 bucket aws s3 cp function.zip \ s3://okabe-lab-deploy-bucket/lambda/moeka-data-collector.zip \ --region ap-northeast-1 # Create the Lambda function via S3 aws lambda create-function \ --function-name moeka-data-collector \ --runtime python3.12 \ --role arn:aws:iam::111122223333:role/lambda-basic-execution-role \ --handler collector.handler \ --code S3Bucket=okabe-lab-deploy-bucket,S3Key=lambda/moeka-data-collector.zip \ --memory-size 1024 \ --timeout 300 \ --region ap-northeast-1 # Update the code via S3 as well aws s3 cp function_v2.zip \ s3://okabe-lab-deploy-bucket/lambda/moeka-data-collector.zip aws lambda update-function-code \ --function-name moeka-data-collector \ --s3-bucket okabe-lab-deploy-bucket \ --s3-key lambda/moeka-data-collector.zip \ --region ap-northeast-1
$ aws s3 cp function.zip \
> s3://okabe-lab-deploy-bucket/lambda/moeka-data-collector.zip \
> --region ap-northeast-1
upload: ./function.zip to s3://okabe-lab-deploy-bucket/lambda/moeka-data-collector.zip
$ aws lambda create-function \
> --function-name moeka-data-collector \
> --runtime python3.12 \
> --role arn:aws:iam::111122223333:role/lambda-basic-execution-role \
> --handler collector.handler \
> --code S3Bucket=okabe-lab-deploy-bucket,S3Key=lambda/moeka-data-collector.zip \
> --memory-size 1024 \
> --timeout 300 \
> --region ap-northeast-1
{
"FunctionName": "moeka-data-collector",
"FunctionArn": "arn:aws:lambda:ap-northeast-1:111122223333:function:moeka-data-collector",
"Runtime": "python3.12",
"Handler": "collector.handler",
"CodeSize": 62914560,
"MemorySize": 1024,
"Timeout": 300,
"State": "Pending",
"LastModified": "2026-03-26T11:00:00.000+0000"
}
$ aws lambda update-function-code \
> --function-name moeka-data-collector \
> --s3-bucket okabe-lab-deploy-bucket \
> --s3-key lambda/moeka-data-collector.zip \
> --region ap-northeast-1
{
"FunctionName": "moeka-data-collector",
"CodeSize": 65011712,
"LastModified": "2026-03-26T11:15:00.000+0000",
"LastUpdateStatus": "Successful"
}
Common Mistakes
Mistake 1: Wrong handler name causes Lambda to fail to find the function
--handler must be specified in the format filename.function_name. A typo in the filename or function name, or including the file extension, will cause Lambda to fail to locate the entry point.
# Less common approach: including the file extension in the handler name / typo in function name aws lambda create-function \ --function-name okabe-time-leap \ --runtime python3.12 \ --role arn:aws:iam::111122223333:role/lambda-basic-execution-role \ --handler index.py.handler \ --zip-file fileb://function.zip # → Results in "Unable to import module 'index.py'" error at runtime
For Python, use index.handler (no extension). For Node.js, use index.handler as well. Separate the filename (without extension) and the exported function name with a dot.
# Common approach: use the format filename (no extension).function_name aws lambda create-function \ --function-name okabe-time-leap \ --runtime python3.12 \ --role arn:aws:iam::111122223333:role/lambda-basic-execution-role \ --handler index.handler \ --zip-file fileb://function.zip
Mistake 2: Wrong directory structure inside the ZIP
If a subdirectory is included inside the ZIP, Lambda cannot find the handler file and will return an error. The entry point file (e.g., index.py) must be at the root of the ZIP.
# Less common approach: zipping a directory, which puts the files under a subdirectory # The structure below results in okabe-time-leap/index.py inside the ZIP cd .. zip -r function.zip okabe-time-leap/ # → Results in "Unable to import module 'index'" error at runtime
When creating a ZIP, move into the directory containing the entry point file first, then compress from there so the file ends up at the root of the ZIP.
# Common approach: run zip from inside the directory containing the entry point file cd okabe-time-leap zip -r ../function.zip . -x "*.git*" -x "__pycache__/*" # ZIP contents: ./index.py, ./requests/, ... unzip -l ../function.zip
Mistake 3: Deployment package exceeds 50 MB compressed, causing upload failure
Direct upload via --zip-file fileb:// is limited to 50 MB compressed. Exceeding this limit causes a RequestEntityTooLargeException error.
# Less common approach: trying to upload a ZIP larger than 50 MB directly zip -r function.zip . -x "*.git*" # If function.zip ends up at 60 MB: aws lambda create-function \ --function-name kurisu-divergence-calc \ --runtime python3.12 \ --role arn:aws:iam::111122223333:role/lambda-basic-execution-role \ --handler calc.handler \ --zip-file fileb://function.zip # → RequestEntityTooLargeException
For packages over 50 MB, upload via S3, or split shared libraries into Lambda Layers to reduce the deployment package size.
# Common approach: upload via S3 (for packages over 50 MB and within 250 MB) aws s3 cp function.zip \ s3://okabe-lab-deploy-bucket/lambda/kurisu-divergence-calc.zip aws lambda create-function \ --function-name kurisu-divergence-calc \ --runtime python3.12 \ --role arn:aws:iam::111122223333:role/lambda-basic-execution-role \ --handler calc.handler \ --code S3Bucket=okabe-lab-deploy-bucket,S3Key=lambda/kurisu-divergence-calc.zip
Summary
There are three main methods for creating a Lambda function. The first is ZIP deployment (direct upload), which is suitable for lightweight functions under 50 MB. Compress the function code and dependencies with the zip command, then upload using aws lambda create-function --zip-file fileb://function.zip. The second is ZIP deployment via S3, used for packages over 50 MB (up to 250 MB unzipped). Upload to an S3 bucket first, then reference it with --code S3Bucket=...S3Key=.... The third is container image deployment (--package-type Image), effective for large dependencies such as machine learning models or packages up to 10 GB. Build an image with a Dockerfile, push it to ECR, and specify its URI in Lambda. Code updates are done with aws lambda update-function-code, while configuration changes (memory, timeout, environment variables, etc.) are done separately with aws lambda update-function-configuration. See Lambda Overview and Basic Operations for more details. For execution role design, see Creating and Assigning IAM Roles.
If you find any errors or copyright issues, please contact us.