Chapter 7 — Serverless (Lambda + API Gateway)

@amitmund July 29, 2026

Day 1 — Deploying and Invoking a Lambda Function

1. Concept Primer

Lambda runs your handler code in response to events, without you managing servers. Floci runs these in real Docker containers, so runtime behavior (timeouts, memory limits, cold starts) is representative rather than simulated.

2. Hands-on Exercise

Write a minimal Python handler, zip it, deploy it, and invoke it directly.

3. Exact Commands

floci start && eval $(floci env)

mkdir -p lambda-day1 && cd lambda-day1
cat > handler.py << 'EOF'
def handler(event, context):
    name = event.get("name", "world")
    return {"statusCode": 200, "body": f"hello, {name}"}
EOF
zip function.zip handler.py

aws iam create-role --role-name lambda-exec-role \
  --assume-role-policy-document '{
    "Version":"2012-10-17",
    "Statement":[{"Effect":"Allow","Principal":{"Service":"lambda.amazonaws.com"},"Action":"sts:AssumeRole"}]
  }'

aws lambda create-function \
  --function-name hello-fn \
  --runtime python3.12 \
  --handler handler.handler \
  --role arn:aws:iam::000000000000:role/lambda-exec-role \
  --zip-file fileb://function.zip

aws lambda invoke --function-name hello-fn \
  --payload '{"name":"floci"}' --cli-binary-format raw-in-base64-out \
  response.json
cat response.json

4. Gotchas

  • Lambda is one of Floci's strongest areas since it runs a real container per invocation — expect genuine cold-start behavior, not an instant mock response.
  • --cli-binary-format raw-in-base64-out is required on recent AWS CLI v2 versions for invoke payloads, or you'll get a base64 encoding error.
  • The IAM role ARN's account ID (000000000000) is a fixed placeholder in local emulators — reuse it verbatim rather than trying to look up a "real" account ID.

5. Self-Check

What's the practical benefit of Lambda running in a real Docker container locally, compared to a runtime that just mocks the response shape?


Day 2 — Wiring an S3 Event Trigger

1. Concept Primer

Lambda can be invoked automatically by event sources instead of direct invoke calls. An S3 bucket notification is the classic example: uploading an object fires the function with the object's bucket/key in the event payload.

2. Hands-on Exercise

Attach the Day 1 function as an S3 event trigger, upload a file, and confirm the function ran by checking its logs.

3. Exact Commands

eval $(floci env)

aws s3 mb s3://trigger-bucket

aws lambda add-permission \
  --function-name hello-fn \
  --statement-id s3invoke \
  --action lambda:InvokeFunction \
  --principal s3.amazonaws.com \
  --source-arn arn:aws:s3:::trigger-bucket

FN_ARN=$(aws lambda get-function --function-name hello-fn --query 'Configuration.FunctionArn' --output text)

aws s3api put-bucket-notification-configuration \
  --bucket trigger-bucket \
  --notification-configuration "{
    \"LambdaFunctionConfigurations\": [{
      \"LambdaFunctionArn\": \"$FN_ARN\",
      \"Events\": [\"s3:ObjectCreated:*\"]
    }]
  }"

echo "triggering upload" > trigger.txt
aws s3 cp trigger.txt s3://trigger-bucket/trigger.txt

aws logs describe-log-groups --log-group-name-prefix /aws/lambda/hello-fn
aws logs tail /aws/lambda/hello-fn --since 5m

4. Gotchas

  • The handler from Day 1 doesn't parse S3 event structure — it'll still run, but event.get("name") won't find anything meaningful in an S3-triggered payload. That's expected; the point here is proving the trigger fires, not processing the payload correctly.
  • If logs appear empty right after upload, wait a couple seconds and re-run logs tail — log delivery isn't always instantaneous even locally.

5. Self-Check

If you wanted the handler to actually read the uploaded object's key, which part of the Lambda event argument would you need to parse?


Day 3 — API Gateway in Front of Lambda

1. Concept Primer

API Gateway exposes an HTTP(S) endpoint that integrates with a backend — commonly Lambda. An HTTP API is the simpler, cheaper, lower-latency option; a REST API offers more features (request validation, usage plans, more integration types) at more complexity.

2. Hands-on Exercise

Create an HTTP API, connect it to the Day 1 Lambda, and call it with plain curl.

3. Exact Commands

eval $(floci env)

FN_ARN=$(aws lambda get-function --function-name hello-fn --query 'Configuration.FunctionArn' --output text)

API_ID=$(aws apigatewayv2 create-api \
  --name hello-api --protocol-type HTTP \
  --target $FN_ARN --query 'ApiId' --output text)

aws lambda add-permission \
  --function-name hello-fn \
  --statement-id apigw-invoke \
  --action lambda:InvokeFunction \
  --principal apigateway.amazonaws.com \
  --source-arn "arn:aws:execute-api:us-east-1:000000000000:$API_ID/*/*"

curl "http://localhost:4566/restapis/$API_ID/\$default/_user_request_/?name=curl-user"

4. Gotchas

  • The --target shortcut on create-api auto-wires a default $default stage and route pointed at your Lambda — convenient for a quick demo, but production setups usually define routes/integrations explicitly for more control.
  • The exact local invoke URL format can differ slightly between Floci versions — if the path above 404s, run aws apigatewayv2 get-api --api-id $API_ID and check the returned endpoint pattern.

5. Self-Check

What's the main tradeoff between choosing an HTTP API versus a REST API for a simple Lambda-backed endpoint?

0 Likes
41 Views
0 Comments

Filters

No filters available for this view.

Reset All