Ravindra BagaleCourses & study guides मराठी Track your progress

Create Your First AWS Lambda Function Step by Step

In What Is AWS Lambda? you met the idea. Now you build a real function end to end: console clicks, the same logic in five languages, a test event, CloudWatch logs, and the IAM execution role with a clear why.

What you'll learn in this chapter

  • Create a function in the Lambda console
  • Write the same handler in Python, Node.js, Java, .NET and Go
  • Use test events and read CloudWatch Logs
  • Understand the execution role and basic permissions
  • Change memory, timeout and environment variables

1. A story: one discount calculator, five teams

Five teams in one company — Python, Node, Java, .NET, Go — all need the same rule: price in, discount out. Instead of five always-on servers, they share one Lambda pattern. Each team ships its own runtime. The trigger and the IAM role stay the same shape.

2. The execution role — why Lambda needs IAM

Why do we need this?

Your code often calls AWS: write logs, read S3, put DynamoDB items. Lambda must prove it is allowed. Access keys inside code leak. A role does not.

What is it?

An execution role is an IAM role that Lambda assumes when your function runs. Trust policy: lambda.amazonaws.com may call sts:AssumeRole. Permissions policy: what the code may do. The AWS managed policy AWSLambdaBasicExecutionRole allows creating log groups and writing log streams — without it, even a Hello function looks "broken" because logs never appear.

Ravindra Bagale's Tip

Add only the extra permissions you need (S3 read, DynamoDB write). Never attach AdministratorAccess to a Lambda role.

3. Handler shape in five languages

What is it?

Every runtime has a handler: a function AWS calls with the event and a context object. Below, each snippet returns {"total": price * (1 - discount)}.

Python 3.12

import json
def lambda_handler(event, context):
    price = float(event["price"])
    discount = float(event.get("discount", 0.1))
    return {"total": round(price * (1 - discount), 2)}

Node.js 20.x

exports.handler = async (event) => {
  const price = Number(event.price);
  const discount = Number(event.discount ?? 0.1);
  return { total: Math.round(price * (1 - discount) * 100) / 100 };
};

Java 17 (handler class)

package example;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
public class Discount implements RequestHandler<Map<String, Object>, Map<String, Object>> {
  public Map<String, Object> handleRequest(Map<String, Object> e, Context c) {
    double price = ((Number) e.get("price")).doubleValue();
    double discount = e.containsKey("discount") ? ((Number) e.get("discount")).doubleValue() : 0.1;
    return Map.of("total", Math.round(price * (1 - discount) * 100.0) / 100.0);
  }
}

.NET 8 (C#)

using Amazon.Lambda.Core;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace Discount;
public class Function {
  public Dictionary<string, double> FunctionHandler(Dictionary<string, double> e, ILambdaContext ctx) {
    var price = e["price"]; var discount = e.GetValueOrDefault("discount", 0.1);
    return new Dictionary<string, double> { ["total"] = Math.Round(price * (1 - discount), 2) };
  }
}

Go 1.x

package main
import ("context"; "github.com/aws/aws-lambda-go/lambda")
type In struct { Price float64 `json:"price"`; Discount float64 `json:"discount"` }
type Out struct { Total float64 `json:"total"` }
func Handle(ctx context.Context, e In) (Out, error) {
  d := e.Discount; if d == 0 { d = 0.1 }
  return Out{Total: e.Price * (1 - d)}, nil
}
func main() { lambda.Start(Handle) }

4. Lab: discount function in the console (Python)

How to do it (step by step)

  1. Lambda → Create function → Author from scratch. Name: discount-lab. Runtime: Python 3.12. Create a new role with basic Lambda permissions.
  2. Paste the Python handler above → Deploy.
  3. Configuration → General configuration → Edit → Memory 256 MB, Timeout 10 s → Save. Why: imports and JSON need a little headroom.
  4. Configuration → Environment variables → Edit → Add DEFAULT_DISCOUNT = 0.1 → Save. Optional: read it with os.environ["DEFAULT_DISCOUNT"].
  5. Test → Create event name ten-percent with JSON:
{"price": 1000, "discount": 0.1}
  1. Test. Expected return: {"total": 900.0}. Note billed duration in the result pane.
  2. Monitor → View CloudWatch logs → open the latest stream → confirm REPORT line with Duration and Memory Size.
  3. Configuration → Permissions → click the role name → confirm it has AWSLambdaBasicExecutionRole. Why: that is how logs are allowed.

Same test via AWS CLI

aws lambda invoke --function-name discount-lab   --payload '{"price":500,"discount":0.2}' --cli-binary-format raw-in-base64-out out.json   --region ap-south-1 && cat out.json
# Expected: {"total": 400.0}

Cleanup

  1. Delete function discount-lab.
  2. IAM → Roles → delete its execution role if unused.

5. Interview questions

Q. What does the handler receive?

The event (input JSON) and a context object (request id, remaining time, memory).

Q. Why Deploy after editing code in the console?

Console edits sit in a draft until you Deploy; tests run the deployed version.

Q. What does AWSLambdaBasicExecutionRole allow?

Creating log groups and writing log streams in CloudWatch Logs.

Q. How do you pass config without hard-coding?

Environment variables on the function, or SSM Parameter Store / Secrets Manager for secrets.

Q. Can one function use two runtimes?

No. One function = one runtime. Make a second function for another language.

Try at home

  1. Recreate discount-lab in Node.js 20.x and invoke with the CLI.
  2. Add an IAM permission for s3:ListBucket on a test bucket and list it from the function.

In short

  1. Create function → write handler → Deploy → Test → check logs.
  2. Execution role = trust Lambda + permissions your code needs.
  3. Same logic ports across Python, Node, Java, .NET, Go.
  4. Memory, timeout and env vars are first knobs to turn.

Practice Tasks

About this scenario

Sangli Turmeric Traders is a spice trading business in Sangli. Dattatray Chavan looks after its IT and cloud work. They count money in INR and run their AWS resources in the ap-south-1 Region. In the tasks below you do real jobs for them using what this lesson teaches. All names, account IDs, IP addresses and numbers are made up for practice.

0 / 12

Easy List functions

Why: See which functions exist in this Region.

What to do: List the Lambda functions in ap-south-1.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Invoke a function

Why: Invoke runs the function now and saves its answer in a file.

What to do: Invoke sanglihaldi-orders-fn and save the response to out.json.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Trust policy for a Lambda role

Why: The trust policy says WHO may take the role.

What to do: Write a trust policy that lets lambda.amazonaws.com assume the role.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Medium Change timeout and memory

Why: More memory also gives more CPU; timeout stops runaway runs.

What to do: Set sanglihaldi-orders-fn to timeout 30 seconds and memory 512 MB.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Medium Let a function write logs

Why: Without these actions, Lambda logs never appear in CloudWatch.

What to do: Allow logs:CreateLogGroup, logs:CreateLogStream, logs:PutLogEvents on arn:aws:logs:*:*:* only.

How:
  1. Start with { "Version": "2012-10-17", "Statement": [ ... ] }.
  2. In each statement write Effect, Action and Resource.
  3. Give only what the task needs (least privilege).
  4. Use double quotes and commas correctly. Click Check answer.

Medium Follow logs live

Why: aws logs tail --follow is like tail -f for CloudWatch Logs.

What to do: Follow the log group /aws/lambda/sanglihaldi-orders-fn live.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Create a Lambda function

Why: Lambda needs the code zip, a runtime, a handler name and an execution role.

What to do: Create function sanglihaldi-orders-fn: runtime python3.12, handler app.handler, role arn:aws:iam::126983531579:role/lambda-basic, code in function.zip.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Set environment variables

Why: Keep settings like table names out of the code.

What to do: Set the environment variable TABLE=sanglihaldi-orders on sanglihaldi-orders-fn.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Invoke with a JSON payload

Why: In CLI v2, raw JSON needs --cli-binary-format raw-in-base64-out.

What to do: Invoke sanglihaldi-orders-fn with payload {"orderId":"o-101"} (raw JSON) and save the reply in out.json.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Lambda GB-seconds

Why: Lambda bills memory × time.

What to do: 1,000,000 invocations, 512 MB memory, 200 ms each. How many GB-seconds?

How:
  1. Write down the numbers the task gives you.
  2. Work it out step by step on paper.
  3. Type only the final answer in the box.
  4. Click Check answer.

Hard Connect an SQS queue to Lambda

Why: An event source mapping makes Lambda poll the queue and process messages in batches.

What to do: Create an event source mapping from queue arn:aws:sqs:ap-south-1:126983531579:sanglihaldi-orders to sanglihaldi-orders-fn with batch size 10.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Hard Let S3 call your function

Why: A resource-based permission is needed before S3 can invoke the function.

What to do: Add permission statement s3invoke to sanglihaldi-orders-fn so s3.amazonaws.com can call lambda:InvokeFunction from bucket arn:aws:s3:::sanglihaldi-uploads.

How:
  1. Read the task and decide which AWS service it is about.
  2. Write aws, then the service name, then the operation (the action word).
  3. Add each needed flag (--name) followed by its value from the task.
  4. Flags can be in any order. Click Check answer.

Revision, comparison and interview cards

Revise this lesson in a few minutes. Save the cards on your phone or download them as PNG files. The QR code on each card opens this lesson.

Revision card: Create a function in the console. Reading docs is not enough. One working function builds confidence. Author from scratch: name, runtime, architecture, execution role. Lambda › Create function › Author from scratch › create › Deploy after edits. hello-lab returns {"ok": true}. Click Test with a blank {}.
Revision card: Create a function in the console · Download PNG · Open card page
Revision card: One idea, many runtimes. Teams speak different languages. The same event shape works across them. Python, Node.js, Java, .NET and Go are common managed runtimes. One function = one runtime. Clone the lab in a second runtime; keep the handler contract the same. Python uses def handler(event, context). Node uses exports.handler = async (event) => ….
Revision card: One idea, many runtimes · Download PNG · Open card page
Revision card: Test events and CloudWatch Logs. Broken JSON in production is painful. Test first with a saved event. Test events are sample JSON. print/console.log goes to CloudWatch Logs. Test tab → create event → invoke. Then Monitor › View CloudWatch logs. Log line "order=42" appears in the latest stream within seconds.
Revision card: Test events and CloudWatch Logs · Download PNG · Open card page
Revision card: Env vars, memory and timeout. Hard-coded table names break when you move from lab to prod. Environment variables hold non-secret config. Memory also buys CPU. Timeout stops runaway work. Configuration › Environment variables; General configuration for memory/timeout. Timeout 3 s fails a 5 s call. Set 10 s for the API lab.
Revision card: Env vars, memory and timeout · Download PNG · Open card page
Interview card: What are the two main handler arguments?. event (payload) and context (metadata: request id, remaining time). Business data lives in event; timeouts and logging use context. context.get_remaining_time_in_millis() helps abort early.
Interview card: What are the two main handler arguments? · Download PNG · Open card page
Interview card: Why must you click Deploy after editing code?. The console editor saves a draft; invokes run the last deployed version. Skipping Deploy makes tests look "stuck" on old code. Edit → Deploy → Test. Same habit for aliases later.
Interview card: Why must you click Deploy after editing code? · Download PNG · Open card page
Interview card: Why prefer an IAM role over access keys in Lambda?. Roles give temporary credentials; keys in code or env can leak. Rotation and least privilege are easier with roles. Never commit AKIA… keys; attach policies to the execution role.
Interview card: Why prefer an IAM role over access keys in Lambda? · Download PNG · Open card page
Interview card: Does raising memory only buy RAM?. No — Lambda allocates more CPU as memory rises. CPU-bound handlers often finish faster at higher memory. Benchmark 256 vs 1024 MB; pick the cheaper GB-s result.
Interview card: Does raising memory only buy RAM? · Download PNG · Open card page

More cards: Ravi Sir's Cards.