How to Deploy Your First AWS Lambda Function from Scratch

What is Serverless Computing?

Imagine you need to do a single, complex calculation. You don't buy a calculator, keep it on your desk, and pay for its electricity every month. Instead, you walk up to a public kiosk, use its calculator for 10 seconds, and walk away. You only pay for those 10 seconds of use. The kiosk owner handles all the maintenance, power, and repairs.

Serverless computing is exactly that, but for code. You write a small, self-contained function, and a cloud provider runs it only when a specific event happens. You pay only for the milliseconds your code runs, not for idle servers.

Try It: The Serverless Lifecycle

In serverless, you don't keep a server "open." You wait for an event. Watch what happens when you trigger a request below.

🙋
User
Idle
Cloud Function
$0.00
Bill
Waiting for event...
📦

1. Functions

Your code is packaged as a single, discrete function—a block that does one job and exits. It's not an always-running application.

🔔

2. Events

The function sits idle until something triggers it: an HTTP request, a database update, or a timer. The event is the "you pressing the equals button."

🧹

3. Statelessness

Every time it runs, it starts from a clean slate. It can't remember data from its last execution. Think of it like a calculator that resets every time you let go of the button.

⚠️ The "Serverless" Myth

Serverless does not mean there are no servers. There absolutely are servers running your code! The term simply means you, the developer, don't have to think about them. The cloud provider handles the provisioning, scaling, and patching. You are abstracted away from the infrastructure.

What is AWS Lambda?

If Serverless is the concept, AWS Lambda is the specific machine that makes it happen. Think of Lambda as a vending machine for code.

You stock it with your function (the snack), configure a specific button to press (the trigger), and it dispenses the result only when that button is pressed. You don't own the machine, you don't pay for its electricity when it's idle, and if 100 people press your button at once, 100 identical machines appear instantly to serve them.

Try It: The Lambda Event Router

Lambda doesn't wake up on its own. It waits for an Event Source. Click a source below to see how the data flows into your function.

Event Sources
AWS Lambda
State: Idle
// Waiting for event...

How Lambda Works: The Lifecycle

When an event source (like an S3 upload) triggers Lambda, a specific chain of events happens automatically. You don't manage the servers; you just manage the code inside this flow.

1

Event Trigger

Something happens in the cloud (a file arrives, a user clicks a button). This creates an event object containing data about what happened.

2

Environment Instantiation

Lambda spins up a secure, isolated micro-VM (a "container") with your runtime (Node.js, Python, etc.). This is the "Cold Start" if it's the first time running.

3

Handler Execution

Your code runs. It receives the event data as an argument. It processes the logic (e.g., resizing an image) and returns a result.

4

Teardown

Once the code finishes, Lambda freezes or destroys the environment. Billing stops immediately. You pay only for the milliseconds the code actually ran.

Your First Lambda Handler

In AWS Lambda, your code is called a Handler. It is simply a function that accepts two arguments: event (the data from the trigger) and context (info about the runtime environment).

index.js
exports.handler = async (event, context) => {
    
    // 1. Log the incoming event data
    console.log('Received event:', JSON.stringify(event));

    // 2. Your business logic here
    const message = 'Hello from Lambda!';

    // 3. Return a response
    return {
        statusCode: 200,
        body: JSON.stringify(message)
    };
};

⚠️ Common Pitfall: "Is it always on?"

Lambda is not a server. It does not sit in a data center waiting for you. If no events trigger your function, no code is running and you pay nothing.

Because of this, you cannot store data in variables inside the function to use in the next run. Every invocation is a fresh start. Always use external databases (like DynamoDB or RDS) for persistent data.

Prerequisites and Setup

Before we can deploy our first function, we need to prepare the environment. Think of this like moving into a new house. You need the house keys (your AWS Account) and a toolbelt (the AWS CLI) to build things inside.

Try It: Configuring Your CLI

The AWS CLI is how you talk to AWS from your computer. Run the setup wizard below to simulate how aws configure works.

user@computer:~
user@computer:~$ aws configure

*This is a simulation. In reality, you will paste your keys from the AWS IAM console.

Step-by-Step: The Real Setup

While the simulation above shows the flow, here is exactly what you need to do on your actual machine:

1

Install AWS CLI

Download the installer from the official AWS documentation for your OS (Windows, macOS, or Linux).

# Verify installation
aws --version
2

Create an IAM User

Never use your Root Account. Go to the IAM Console, create a user (e.g., lambda-dev), and attach the AWSLambda_FullAccess policy.

⚠️ For production, use "Least Privilege" policies.

3

Get Access Keys

In the IAM user settings, go to Security CredentialsCreate Access Key. Copy the Access Key ID and Secret Access Key.

4

Run aws configure

Paste your keys into the terminal when prompted. Set your region (e.g., us-east-1).

⚠️ Myth: "I can use any programming language"

Lambda doesn't run any code arbitrarily. It provides managed runtimes (Node.js, Python, Java, Go, .NET, Ruby).

Why? AWS manages the OS and runtime patches for these specific languages.

(Advanced Note: You can use custom container images for unsupported languages, but that requires managing your own OS and security updates. Stick to managed runtimes for now!)

Creating Your First Lambda Function

Think of creating your first Lambda function as writing a single, precise instruction on a notecard. You don't build a whole factory; you just write the instruction.

When Lambda "picks up" that card (via a trigger), it reads exactly what you wrote, runs it, and puts it down. For your first card, let's keep it simple: a function that takes a name and says "Hello".

index.js
exports.helloWorld = async (event) => {
    
    // 1. Get a name from the event, or use 'World'
    const name = event.name || 'World';
    
    // 2. Create a friendly message
    const message = `Hello, ${name}!`;

    // 3. Return the result
    return {
        statusCode: 200,
        body: JSON.stringify(message)
    };
};

The "Handler" Connection

In the code above, the magic line is exports.helloWorld. This is your Handler.

When you deploy this code to AWS, you must tell the Lambda service exactly where to find this instruction. You do this by combining the File Name and the Function Name.

Try It: The Deployment Configurator

AWS Lambda needs to know exactly how to find your code. File Name + Function Name = The Handler. Configure the settings below to see how the deployment command is built.

Usually index.js or app.py (without extension)

The exact name of your exported function

CLI
Generated Command:
aws lambda create-function \
  --function-name my-first-function \
  --runtime nodejs20.x \
  --role arn:aws:iam::...:role/lambda-role \
  --handler index.helloWorld \
  --zip-file fileb://function.zip

The "Handler" Pitfall

The most common mistake beginners make is a mismatch between the code and the deployment command.

⚠️ Why does it say "Handler not found"?

If your code says exports.helloWorld but your command says --handler index.main, Lambda will panic. It looks for a function named main inside index.js, doesn't find it, and throws an error.

Rule of Thumb: Always double-check the string after --handler. It must be filename.functionname. No typos allowed!

Configuring the Execution Environment

Now that we have our code, we need to tune the engine. Think of your Lambda function's memory setting like adjusting the wattage on a power tool.

Give it more power (memory), and it runs faster—but you pay more per millisecond. Set it too low, and it might run slowly or even time out. The timeout is simply how long you'll wait for it to finish before Lambda pulls the plug. You're trading off speed against cost.

Try It: The Memory vs. Cost Trade-off

In Lambda, Memory controls CPU. More memory = faster execution. But you pay for GB-seconds. Watch how the total cost changes as you slide the dial.

128 MB (Slow) 1024 MB (Fast)
Est. Duration: 1000 ms
Cost per ms: $0.000000016
Total Cost: $0.00001600
Speed: 1x

Technical Reasoning: The Scaling Knob

Why does memory affect speed? In Lambda, memory is the primary scaling knob. When you allocate 256 MB, you get a proportional share of CPU and network bandwidth.

  • Double the memory: Your code generally runs roughly twice as fast (though not always linearly).
  • Billing Math: You pay for GB-seconds. A function that uses 512 MB for 100ms costs exactly twice as much as the same function using 256 MB for 100ms.
  • Timeout Safety Net: The timeout (default 3 seconds, max 15 minutes) is a hard limit. If your function runs longer, Lambda terminates it and logs a Task timed out error.
CLI Command
aws lambda update-function-configuration \
    --function-name my-first-function \
    --memory-size 512 \
    --timeout 10

Setting Environment Variables

Environment variables are key-value pairs injected into your function's runtime environment at invocation. They're perfect for configuration that changes between deployments (like database names, feature flags, or API keys) without hardcoding them.

Try It: Injecting Configuration

Notice how the code stays the same, but the behavior changes based on the environment. Toggle the "Stage" to see how the function adapts.

Environment Variables

ENV
Runtime Output:
const stage = process.env.STAGE;
console.log(`Running in ${stage} mode`);

// Output:
> Running in development mode
index.js
exports.handler = async (event) => {
    const stage = process.env.STAGE; // Reads from Environment
    console.log(`Running in ${stage} mode`);
    
    return {
        statusCode: 200,
        body: `Environment: ${stage}`
    };
};

The "Identity Crisis": IAM Roles

Here is the most common pitfall for beginners. Your function has an Execution Role (an IAM Role). This is its digital identity card.

The Mistake: Assuming that because you (the developer) have permission to access S3, your function does too. It does not. The function is a separate entity. It must have its own explicit policies attached to its role.

Try It: The Gatekeeper Check

Your function tries to read a file from S3. Toggle the "Role Permissions" to see if the Gatekeeper (AWS) allows access.

Lambda Function
📦 S3 Bucket
AWS S3

⚠️ The "Access Denied" Nightmare

If your function tries to s3.getObject() without the right policy attached to its Execution Role, you will see an error like AccessDenied: Access Denied.

Rule of Thumb: Whenever your function interacts with another AWS service, immediately check the execution role's policies. Start with least privilege—grant only the exact actions (e.g., s3:GetObject) on the exact resources needed.

Testing and Invoking Your Function

You've written the code. Now, how do you know it works? You don't need to wait for a user to visit your website. You can press the "Call Button" yourself.

In the AWS Lambda world, this is called Invoking your function. You can do this visually in the console or programmatically via the command line. Let's see how the "Test Console" works.

Try It: The Lambda Test Console

In the AWS Console, you configure a "Test Event" (JSON input) and click Test. Watch how the console simulates the execution and shows you the logs.

Test Event (JSON)
{
  "name": "Professor Pixel",
  "action": "teach"
}
Execution Result
Success
// Click 'Test' to run...

Invoking via AWS CLI

While the console is great for manual testing, developers prefer the Command Line Interface (CLI). It allows you to automate tests and scripts.

Terminal
aws lambda invoke \
    --function-name my-first-function \
    --payload '{"name": "CLI User"}' \
    response.json

Try It: The CLI Response

When you run the command above, the terminal doesn't just print the result to the screen—it writes it to a file. Watch the file system update below.

💻
Your Laptop
📄
response.json

Common Pitfall: "Function Times Out"

The most common runtime error is "Task timed out". This happens when your code takes longer to run than the Timeout setting you configured.

Try It: The Timeout Debugger

Imagine your code is a runner. The Timeout Limit is the finish line. If the runner doesn't cross it in time, AWS stops them. Adjust the settings to see if the code succeeds or fails.

Fast (100ms) Slow (5000ms)
3s (Default) 10s
TIMEOUT LIMIT
Running...

⚠️ Why did it time out?

If you see Task timed out, check these three things immediately:

  • External Calls: Is your code waiting for a slow database or API that isn't responding?
  • Infinite Loops: Did you forget to break out of a loop?
  • Memory/CPU: Is the function underpowered? Sometimes giving it more memory (which gives it more CPU) makes it fast enough to finish before the timeout.

Deploying via the AWS Console

While the CLI is powerful for automation, the AWS Console is your visual workshop. It's a guided wizard that walks you through the deployment process, handling the heavy lifting of packaging and configuration for you.

Think of this as packing a suitcase. You need to put your clothes (code) and toiletries (dependencies) into the bag (zip file) correctly before you check it in. If you pack it wrong, the airline (AWS) rejects it.

Try It: The Zip Structure Validator

A common mistake is zipping the folder instead of the contents. Lambda expects files at the root. Use the buttons below to simulate zipping different structures and see if AWS accepts them.

Your Local Folder
📄 index.js
📁 node_modules/
📦
Waiting...
What AWS sees:
// Structure preview...

The Deployment Wizard

Once your zip file is ready, the console guides you through the setup. You'll define the function's identity (Name, Runtime) and its permissions (Role).

Try It: The AWS Console Wizard

Fill out the form below to simulate creating your first function. Notice how the Handler must match your code structure.

This creates a basic IAM role for you.

📦
Upload from .zip file
my-first-function.zip (15 KB)

Common Pitfall: The "Zip" Trap

The most frequent error beginners face is the "Nested Folder" Error.

❌ The Wrong Way (Nested)

If you select the parent folder and zip it, AWS extracts it into a subfolder.

/var/task/my-project/index.js ← Lambda can't find this!
/var/task/my-project/node_modules/

✅ The Right Way (Root)

You must zip the contents so files sit at the root.

/var/task/index.js ← Lambda finds this!
/var/task/node_modules/

⚠️ Missing Modules?

If you see Cannot find module 'axios', it usually means your node_modules folder wasn't included in the zip, or it was placed in the wrong directory.

Pro Tip: On macOS, right-click your folder and select "Compress" to create a zip. On Windows, select the files inside the folder, right-click, and select "Send to > Compressed (zipped) folder".

Monitoring and Logging

Think of your Lambda function as an autonomous delivery drone. Once it's airborne, you can't see inside it. CloudWatch is the control tower's radar and flight recorder.

It automatically captures two critical things:

  1. Metrics: The "vital signs" (how many times it flew, how long each flight took, how much memory it used). This is your high-level health dashboard.
  2. Logs: The "black box" — a detailed, chronological transcript of everything your function console.log-ed, plus system messages. This is your primary debugging tool.

Try It: The CloudWatch Control Tower

Lambda sends data to CloudWatch automatically. Watch how the "Vital Signs" (Metrics) and "Flight Recorder" (Logs) update when your function runs.

Lambda Function
📡 CloudWatch
Vital Signs (Metrics)
Invocations
0
Avg Duration
0 ms
Flight Recorder (Logs)
// Waiting for data...

Setting Up Logs and Metrics

Logs are automatic, but structured access is key. Every time your Lambda runs, AWS creates a log stream in a CloudWatch Logs group named /aws/lambda/your-function-name.

To see logs for a specific invocation, go to the Monitor tab in the Lambda console and click View logs in CloudWatch. You will see entries like:

CloudWatch Log Stream
START RequestId: 8675309 Version: $LATEST
INFO Received event: {"name": "Professor Pixel"}
Processing logic...
END RequestId: 8675309
REPORT RequestId: 8675309  Duration: 1.23 ms  Billed Duration: 2 ms  Memory Size: 128 MB  Max Memory Used: 75 MB

Pro Tip: If you prefer the command line, you can "tail" your logs in real-time (like tail -f) using:

Terminal
aws logs tail /aws/lambda/my-first-function --follow

The Cost Trap: Log Retention

Here is a critical lesson for your wallet: CloudWatch Logs retain data forever by default.

Every console.log accumulates in S3-backed storage. For a busy function, this can grow to gigabytes per day. You pay for this storage. A common beginner surprise is an unexpectedly high AWS bill because log data was never cleaned up.

Try It: The Retention Simulator

Log data piles up every day. If you don't set a retention policy, it stays forever. Use the slider to see how storage costs grow over time with different retention settings.

1 Day 7 Days 30 Days Forever
Est. Daily Logs: 100 MB
Storage Cost (per GB/mo): $0.03
Monthly Cost: $0.00
0 MB
CLI Command
aws logs put-retention-policy \
    --log-group-name /aws/lambda/my-first-function \
    --retention-in-days 30

⚠️ The "Log Sprawl" Nightmare

If you don't set a retention policy, your log group grows indefinitely. You pay for every gigabyte stored.

Rule of Thumb: Always set a retention policy on every new Lambda function's log group within your first deployment. Start with 30 days for production (allows for post-mortem debugging) and 7 days for development. Treat it like auto-deleting your email trash—it's basic maintenance.

Frequently Asked Questions (FAQ)

Welcome to the FAQ corner! Even the best developers have questions when they start with Lambda. Here, we'll tackle the most common hurdles: from "How do I trigger this?" to "Why is it so expensive?" Let's clear up the confusion.

Q: How do I trigger a Lambda function?

Lambda functions are event-driven. They don't run on their own; they wait for a specific event to "press the button." The most common trigger for web apps is the API Gateway, which converts web traffic (HTTP requests) into Lambda events.

Triggers Configuration
No triggers attached yet.
Click "Add Trigger" to connect a source.

How it works:

  • 1. You select API Gateway from the menu.
  • 2. AWS creates a new API and generates a unique URL (e.g., `https://abc123.execute-api...`).
  • 3. Any HTTP request to that URL instantly invokes your function.

*Remember: Without a trigger, your code sits idle forever.

Q: Why does my Lambda function fail to start?

"Fail to start" usually means Lambda can't initialize your code. The top causes are Handler Mismatch (Lambda can't find your function) or Missing Dependencies (missing libraries).

CloudWatch Logs
// Waiting for execution...

Q: Can I use Python for my Lambda function?

Absolutely! Python is a first-class runtime. The structure is identical to Node.js: a single file with a handler function.

exports.handler = async (event) => {
    const name = event.name || 'World';
    return {
        statusCode: 200,
        body: `Hello, ${name}!`
    };
};
Key Difference: In Python, the file is usually lambda_function.py and the function is lambda_handler.

Q: What are the cost implications of using Lambda?

You pay for Requests (how many times it runs) and Duration (how long it runs). Interestingly, giving your function more memory often makes it run faster, which can actually lower your bill.

128 MB 1024 MB
Est. Duration: 1000 ms
Requests (1M): $0.20
Total Cost: $0.20
CPU Speed: 1x

*Increasing memory increases CPU, reducing duration and often cost.

Q: How do I manage environment variables securely?

Environment variables are great for config, but never put secrets (passwords, keys) directly in them if you can avoid it. Use AWS Secrets Manager instead.

Bad Way: Hardcoded
const dbPass = "super_secret_password";
Good Way: Secrets Manager
const secret = await getSecret('db-pass');

Secrets Manager encrypts your data and allows you to rotate keys automatically without touching your code.

Q: When should I avoid using Lambda?

Lambda is amazing, but it has a 15-minute hard limit. If your task takes longer, or if you need a persistent connection (like a WebSocket), use a traditional server (EC2 or Fargate).

Task Duration 15 Minutes Limit
Current Task: 5 min

Q: What are the limits on package size and memory?

Direct upload zips are limited to 50 MB. If your dependencies are huge, you'll need to use Layers or a Container Image (up to 10 GB).

Package Size 25 MB
0 MB 50 MB Limit 100 MB

Q: How do I troubleshoot cold start delays?

Cold starts happen when Lambda creates a new environment (after idle time). To fix this, reduce package size, increase memory (more CPU = faster init), or use Provisioned Concurrency to keep environments warm.

Latency 1500 ms
Cold
Warm
Initialization Execution
Small (Fast) Large (Slow)

Tip: Smaller packages download faster, reducing the "Cold" phase.

⚠️ The "Log Sprawl" Nightmare

If you don't set a retention policy, your log group grows indefinitely. You pay for every gigabyte stored.

Rule of Thumb: Always set a retention policy on every new Lambda function's log group within your first deployment. Start with 30 days for production and 7 days for development.

Post a Comment

Previous Post Next Post