iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Lambda

AWS Lambda runs your code in response to events, with no server to manage. You pay per invocation + execution time; cold starts add latency on the first call.

Node Lambda + API GW + IAM + observability

EXAMPLE
# 1) Minimal Node handler (Lambda function)
# handler.mjs
export const handler = async (event, context) => {
    console.log('event:', JSON.stringify(event));
    return {
        statusCode: 200,
        headers:    { 'content-type': 'application/json' },
        body:       JSON.stringify({ ok: true, requestId: context.awsRequestId }),
    };
};

# Package + deploy via AWS CLI
zip function.zip handler.mjs
aws lambda create-function \
    --function-name hello \
    --runtime nodejs20.x \
    --handler handler.handler \
    --role arn:aws:iam::123456789012:role/lambda-basic-exec \
    --zip-file fileb://function.zip \
    --architectures arm64 \
    --memory-size 256 \
    --timeout 10

# Update code
aws lambda update-function-code --function-name hello --zip-file fileb://function.zip

# 2) Invoke
aws lambda invoke --function-name hello --payload '{"hi":"there"}' /tmp/out.json && cat /tmp/out.json

# 3) Wire to API Gateway HTTP API
aws apigatewayv2 create-api \
    --name hello-api --protocol-type HTTP \
    --target arn:aws:lambda:us-east-1:123456789012:function:hello

aws lambda add-permission \
    --function-name hello \
    --statement-id apigw \
    --action lambda:InvokeFunction \
    --principal apigateway.amazonaws.com \
    --source-arn 'arn:aws:execute-api:us-east-1:123456789012:*/*'

# Now: GET https://<api-id>.execute-api.us-east-1.amazonaws.com/ → invokes hello

# 4) IAM role — start minimal, attach managed policy for CloudWatch Logs
aws iam create-role \
    --role-name lambda-basic-exec \
    --assume-role-policy-document '{
        "Version":"2012-10-17",
        "Statement":[{
            "Effect":"Allow",
            "Principal":{"Service":"lambda.amazonaws.com"},
            "Action":"sts:AssumeRole"
        }]
    }'
aws iam attach-role-policy --role-name lambda-basic-exec \
    --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

# Add per-service permissions as needed (read S3, write DynamoDB)

# 5) Common event sources
# API Gateway       (HTTP / REST)
# S3                (object created/deleted)
# DynamoDB Streams  (row change)
# SQS               (messages)
# EventBridge       (cron + custom events)
# Step Functions    (workflow state)
# CloudFront        (Edge — lighter cold start)
# SNS               (pub/sub fanout)

# 6) Cold starts + tuning
# - Smaller bundle = faster cold start. Bundle (esbuild) + tree-shake.
# - arm64 + 512-1024 MB = best price/perf for most code.
# - Reuse SDK clients OUTSIDE the handler — they survive between warm calls.
import { S3Client } from '@aws-sdk/client-s3';
const s3 = new S3Client({});                  // module-level — reused
export const handler = async (event) => {
    await s3.send(new GetObjectCommand({ /* ... */ }));
};

# - Provisioned Concurrency keeps containers warm (extra cost, near-zero cold start)
aws lambda put-provisioned-concurrency-config --function-name hello --qualifier 1 --provisioned-concurrent-executions 5

# 7) Environment variables
aws lambda update-function-configuration \
    --function-name hello \
    --environment 'Variables={NODE_ENV=production,LOG_LEVEL=info}'

# 8) Secrets
# - Don't put secrets in env vars (they show in console)
# - Use AWS Secrets Manager / Parameter Store, fetch at cold start, cache in module scope
import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm';
const ssm = new SSMClient({});
let dbUrl;
async function getDbUrl() {
    if (!dbUrl) {
        const r = await ssm.send(new GetParameterCommand({
            Name: '/prod/app/db_url', WithDecryption: true,
        }));
        dbUrl = r.Parameter.Value;
    }
    return dbUrl;
}

# 9) Observability
# - Logs auto-stream to CloudWatch Logs (/aws/lambda/<name>)
# - Structured logging — log JSON, query via CloudWatch Logs Insights
# - X-Ray tracing — add AWSXRayDaemonWriteAccess policy + AWS_XRAY_DAEMON_ADDRESS env
# - Lambda Powertools — typed logging, metrics, tracing for Node/Python/TS

# 10) Local dev + test
# - AWS SAM (sam local invoke), Serverless Framework, AWS CDK, SST
# - Run unit tests like normal Node code; integration tests with LocalStack

# 11) Anti-patterns
# - Massive monolithic Lambdas — split by route, share libs
# - Long-running Lambdas (>1 min on hot path) — move to ECS/Fargate or Step Functions
# - DB connection per invocation — use RDS Proxy or short-lived HTTP databases (Aurora Data API, DynamoDB)
# - Sync invocations chained — fan-out via EventBridge or SQS

# 12) Cost ballpark
# 1M invocations free per month
# After that: $0.20 per 1M + GB-second time
# 100ms @ 512MB = ~5e-6 per invocation

Why it matters

Pin module-scope SDK clients + DB connections; secrets via Parameter Store / Secrets Manager, never env vars. Cold-start work happens once per container; design Lambdas like “init once, handle many.”

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
# Serverless compute. Bring code, AWS runs it on every event.
export const handler = async (event) => ({ statusCode: 200, body: 'OK' });
Try it Yourself »

Exercise

Invoke a Lambda function via CLI.

aws lambda --function-name fn out.json

Test yourself

Q1. Lambda is…
Q2. Lambda pricing is based on…
Q3. A common trigger is…

Discussion

Loading…