View a markdown version of this page

Creating your first Lambda function - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

Creating your first Lambda function

The following code example shows how to:

  • Create an IAM role for Lambda

  • Create function code

  • Create a Lambda function

  • Test your Lambda function

  • Clean up resources

Bash
AWS CLI with Bash script
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials repository.

#!/bin/bash # AWS Lambda - Create Your First Function # This script creates a Lambda function, invokes it with a test event, # views CloudWatch logs, and cleans up all resources. # # Source: https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html # # Resources created: # - IAM role (Lambda execution role with basic logging permissions) # - Lambda function (Python 3.13 or Node.js 22.x runtime) # - CloudWatch log group (created automatically by Lambda on invocation) set -eE ############################################################################### # Setup ############################################################################### UNIQUE_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1) FUNCTION_NAME="my-lambda-function-${UNIQUE_ID}" ROLE_NAME="lambda-execution-role-${UNIQUE_ID}" LOG_GROUP_NAME="/aws/lambda/${FUNCTION_NAME}" TEMP_DIR=$(mktemp -d) LOG_FILE="${TEMP_DIR}/lambda-gettingstarted.log" exec > >(tee -a "$LOG_FILE") 2>&1 declare -a CREATED_RESOURCES ############################################################################### # Helper functions ############################################################################### cleanup_resources() { # Disable error trap to prevent recursion during cleanup trap - ERR set +eE echo "" echo "Cleaning up resources..." echo "" for ((i=${#CREATED_RESOURCES[@]}-1; i>=0; i--)); do local RESOURCE="${CREATED_RESOURCES[$i]}" local TYPE="${RESOURCE%%:*}" local NAME="${RESOURCE#*:}" case "$TYPE" in log-group) echo "Deleting CloudWatch log group: ${NAME}" aws logs delete-log-group \ --log-group-name "$NAME" 2>&1 || echo " WARNING: Could not delete log group ${NAME}." ;; lambda-function) echo "Deleting Lambda function: ${NAME}" aws lambda delete-function \ --function-name "$NAME" 2>&1 || echo " WARNING: Could not delete Lambda function ${NAME}." echo " Waiting for function deletion to complete..." local DELETE_WAIT=0 while aws lambda get-function --function-name "$NAME" > /dev/null 2>&1; do sleep 2 DELETE_WAIT=$((DELETE_WAIT + 2)) if [ "$DELETE_WAIT" -ge 60 ]; then echo " WARNING: Timed out waiting for function deletion." break fi done ;; iam-role-policy) local ROLE_PART="${NAME%%|*}" local POLICY_PART="${NAME#*|}" echo "Detaching policy from role: ${ROLE_PART}" aws iam detach-role-policy \ --role-name "$ROLE_PART" \ --policy-arn "$POLICY_PART" 2>&1 || echo " WARNING: Could not detach policy from role ${ROLE_PART}." ;; iam-role) echo "Deleting IAM role: ${NAME}" aws iam delete-role \ --role-name "$NAME" 2>&1 || echo " WARNING: Could not delete IAM role ${NAME}." ;; esac done if [ -d "$TEMP_DIR" ]; then rm -rf "$TEMP_DIR" fi echo "" echo "Cleanup complete." } handle_error() { echo "" echo "===========================================" echo "ERROR: Script failed at $1" echo "===========================================" echo "" if [ ${#CREATED_RESOURCES[@]} -gt 0 ]; then echo "Attempting to clean up ${#CREATED_RESOURCES[@]} resource(s)..." cleanup_resources fi exit 1 } trap 'handle_error "line $LINENO"' ERR wait_for_resource() { local DESCRIPTION="$1" local COMMAND="$2" local TARGET_VALUE="$3" local TIMEOUT=300 local ELAPSED=0 local INTERVAL=5 echo "Waiting for ${DESCRIPTION}..." while true; do local RESULT RESULT=$(eval "$COMMAND" 2>&1) || true if echo "$RESULT" | grep -q "$TARGET_VALUE"; then echo " ${DESCRIPTION} is ready." return 0 fi if [ "$ELAPSED" -ge "$TIMEOUT" ]; then echo "ERROR: Timed out waiting for ${DESCRIPTION} after ${TIMEOUT} seconds." return 1 fi sleep "$INTERVAL" ELAPSED=$((ELAPSED + INTERVAL)) done } ############################################################################### # Region pre-check ############################################################################### CONFIGURED_REGION=$(aws configure get region 2>/dev/null || true) if [ -z "$CONFIGURED_REGION" ] && [ -z "$AWS_DEFAULT_REGION" ] && [ -z "$AWS_REGION" ]; then echo "ERROR: No AWS region configured." echo "Run 'aws configure set region <region>' or export AWS_DEFAULT_REGION." exit 1 fi ############################################################################### # Runtime selection ############################################################################### echo "" echo "===========================================" echo "AWS Lambda - Create Your First Function" echo "===========================================" echo "" echo "Select a runtime for your Lambda function:" echo " 1) Python 3.13" echo " 2) Node.js 22.x" echo "" echo "Enter your choice (1 or 2): " read -r RUNTIME_CHOICE case "$RUNTIME_CHOICE" in 1) RUNTIME="python3.13" HANDLER="lambda_function.lambda_handler" CODE_FILE="lambda_function.py" cat > "${TEMP_DIR}/${CODE_FILE}" << 'PYTHON_EOF' import json import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): length = event['length'] width = event['width'] area = calculate_area(length, width) print(f'The area is {area}') logger.info(f'CloudWatch logs group: {context.log_group_name}') return json.dumps({'area': area}) def calculate_area(length, width): return length * width PYTHON_EOF echo "Selected runtime: Python 3.13" ;; 2) RUNTIME="nodejs22.x" HANDLER="index.handler" CODE_FILE="index.mjs" cat > "${TEMP_DIR}/${CODE_FILE}" << 'NODEJS_EOF' export const handler = async (event, context) => { const area = event.length * event.width; console.log(`The area is ${area}`); console.log('CloudWatch log group: ', context.logGroupName); return JSON.stringify({area}); }; NODEJS_EOF echo "Selected runtime: Node.js 22.x" ;; *) echo "ERROR: Invalid choice. Please enter 1 or 2." exit 1 ;; esac ############################################################################### # Step 1: Create IAM execution role ############################################################################### echo "" echo "===========================================" echo "Step 1: Create IAM execution role" echo "===========================================" echo "" TRUST_POLICY='{ "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }' echo "Creating IAM role: ${ROLE_NAME}" ROLE_OUTPUT=$(aws iam create-role \ --role-name "$ROLE_NAME" \ --assume-role-policy-document "$TRUST_POLICY" \ --query 'Role.Arn' \ --output text 2>&1) echo "$ROLE_OUTPUT" ROLE_ARN="$ROLE_OUTPUT" CREATED_RESOURCES+=("iam-role:${ROLE_NAME}") echo "Role ARN: ${ROLE_ARN}" echo "" echo "Attaching AWSLambdaBasicExecutionRole policy..." aws iam attach-role-policy \ --role-name "$ROLE_NAME" \ --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 2>&1 CREATED_RESOURCES+=("iam-role-policy:${ROLE_NAME}|arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole") echo "Policy attached." # IAM roles can take a few seconds to propagate echo "Waiting for IAM role to propagate..." sleep 10 ############################################################################### # Step 2: Create Lambda function ############################################################################### echo "" echo "===========================================" echo "Step 2: Create Lambda function" echo "===========================================" echo "" echo "Creating deployment package..." ORIGINAL_DIR=$(pwd) cd "$TEMP_DIR" zip -j function.zip "$CODE_FILE" > /dev/null 2>&1 cd "$ORIGINAL_DIR" echo "Creating Lambda function: ${FUNCTION_NAME}" echo " Runtime: ${RUNTIME}" echo " Handler: ${HANDLER}" echo "" CREATE_OUTPUT=$(aws lambda create-function \ --function-name "$FUNCTION_NAME" \ --runtime "$RUNTIME" \ --role "$ROLE_ARN" \ --handler "$HANDLER" \ --architectures x86_64 \ --zip-file "fileb://${TEMP_DIR}/function.zip" \ --query '[FunctionName, FunctionArn, Runtime, State]' \ --output text 2>&1) echo "$CREATE_OUTPUT" CREATED_RESOURCES+=("lambda-function:${FUNCTION_NAME}") wait_for_resource "Lambda function to become Active" \ "aws lambda get-function-configuration --function-name ${FUNCTION_NAME} --query State --output text" \ "Active" ############################################################################### # Step 3: Invoke the function ############################################################################### echo "" echo "===========================================" echo "Step 3: Invoke the function" echo "===========================================" echo "" TEST_EVENT='{"length": 6, "width": 7}' echo "Invoking function with test event: ${TEST_EVENT}" echo "" echo "$TEST_EVENT" > "${TEMP_DIR}/test-event.json" INVOKE_OUTPUT=$(aws lambda invoke \ --function-name "$FUNCTION_NAME" \ --payload "fileb://${TEMP_DIR}/test-event.json" \ --cli-read-timeout 30 \ "${TEMP_DIR}/response.json" 2>&1) echo "$INVOKE_OUTPUT" RESPONSE=$(cat "${TEMP_DIR}/response.json") echo "" echo "Function response: ${RESPONSE}" echo "" if echo "$INVOKE_OUTPUT" | grep -qi "functionerror"; then echo "WARNING: Function returned an error." fi ############################################################################### # Step 4: View CloudWatch logs ############################################################################### echo "" echo "===========================================" echo "Step 4: View CloudWatch Logs" echo "===========================================" echo "" echo "Log group: ${LOG_GROUP_NAME}" echo "" echo "Waiting for CloudWatch logs to be available..." LOG_STREAMS="" for i in $(seq 1 6); do LOG_STREAMS=$(aws logs describe-log-streams \ --log-group-name "$LOG_GROUP_NAME" \ --order-by LastEventTime \ --descending \ --query 'logStreams[0].logStreamName' \ --output text 2>/dev/null) || true if [ -n "$LOG_STREAMS" ] && [ "$LOG_STREAMS" != "None" ]; then break fi LOG_STREAMS="" sleep 5 done if [ -n "$LOG_STREAMS" ] && [ "$LOG_STREAMS" != "None" ]; then echo "Latest log stream: ${LOG_STREAMS}" echo "" echo "--- Log events ---" LOG_EVENTS=$(aws logs get-log-events \ --log-group-name "$LOG_GROUP_NAME" \ --log-stream-name "$LOG_STREAMS" \ --query 'events[].message' \ --output text 2>&1) || true echo "$LOG_EVENTS" echo "--- End of log events ---" else echo "No log streams found yet. Logs may take a moment to appear." echo "You can view them in the CloudWatch console:" echo " Log group: ${LOG_GROUP_NAME}" fi CREATED_RESOURCES+=("log-group:${LOG_GROUP_NAME}") ############################################################################### # Summary and cleanup ############################################################################### echo "" echo "===========================================" echo "SUMMARY" echo "===========================================" echo "" echo "Resources created:" echo " IAM role: ${ROLE_NAME}" echo " Lambda function: ${FUNCTION_NAME}" echo " CloudWatch logs: ${LOG_GROUP_NAME}" echo "" echo "===========================================" echo "CLEANUP CONFIRMATION" echo "===========================================" echo "" echo "Do you want to clean up all created resources? (y/n): " read -r CLEANUP_CHOICE if [[ "$CLEANUP_CHOICE" =~ ^[Yy]$ ]]; then cleanup_resources else echo "" echo "Resources were NOT deleted. To clean up manually, run:" echo "" echo " # Delete the Lambda function" echo " aws lambda delete-function --function-name ${FUNCTION_NAME}" echo "" echo " # Delete the CloudWatch log group" echo " aws logs delete-log-group --log-group-name ${LOG_GROUP_NAME}" echo "" echo " # Detach the policy and delete the IAM role" echo " aws iam detach-role-policy --role-name ${ROLE_NAME} --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" echo " aws iam delete-role --role-name ${ROLE_NAME}" echo "" if [ -d "$TEMP_DIR" ]; then rm -rf "$TEMP_DIR" fi fi echo "" echo "Done."