Part 3: Building Your First Lambda Function

From Learning to Doing

After understanding the theory, I remember being eager to build my first Lambda function. This guide walks you through creating a practical, production-ready function based on my actual projects.

What We'll Build

We're creating a User Registration API that:

  • Validates user input

  • Stores data in DynamoDB

  • Sends confirmation emails via SNS

  • Returns appropriate HTTP responses

This mirrors a real feature I built for a SaaS application.

Prerequisites Setup

Before coding, ensure you have these tools installed. I use these daily:

Install AWS CLI

# macOS
brew install awscli

# Verify installation
aws --version

Configure AWS Credentials

Install AWS SAM CLI

Project Structure

Here's the directory structure I use for all my Lambda projects:

Step 1: Create the Project

Step 2: Define Requirements

Create requirements.txt:

Why these dependencies?

  • boto3: AWS SDK (already in Lambda, but pinned for local testing)

  • pydantic: Data validation (learned this after dealing with bad input)

  • python-json-logger: Structured logging (essential for debugging)

Step 3: Build the Data Models

Create src/models.py:

Step 4: Create Validators

Create src/validators.py:

Step 5: DynamoDB Service

Create src/services/dynamodb.py:

Step 6: Notification Service

Create src/services/notification.py:

Step 7: Main Handler

Create src/handler.py:

Complete Request Flow

Here's how the entire system works together:

spinner

Step 8: SAM Template

Create template.yaml:

Step 9: Create Test Event

Create events/api_gateway_event.json:

Step 10: Local Testing

Build and Test Locally

Test with curl

Step 11: Deploy to AWS

Deployment Flow

spinner

Step 12: Test Production Endpoint

Monitoring Your Function

View Logs

Check Metrics in CloudWatch

Key metrics I monitor:

  • Invocations: Total number of calls

  • Duration: Execution time

  • Errors: Failed invocations

  • Throttles: Rate-limited requests

  • Concurrent Executions: Number of simultaneous runs

Common Issues I've Encountered

Issue 1: Cold Start Latency

Problem: First request takes 2-3 seconds

Solution:

  • Use provisioned concurrency for critical APIs

  • Optimize dependencies

  • Keep deployment package small

Issue 2: Timeout Errors

Problem: Function times out processing large payloads

Solution:

  • Increase timeout in template.yaml

  • Break down into smaller operations

  • Use async processing for long tasks

Issue 3: Permission Errors

Problem: AccessDeniedException when accessing DynamoDB

Solution:

  • Verify IAM policies in SAM template

  • Check resource names match exactly

  • Review CloudWatch logs for specific permission issues

Key Takeaways

From building this function:

  1. Structure Matters: Organized code is easier to test and maintain

  2. Validate Early: Catch bad input before processing

  3. Log Everything: Structured logs are invaluable for debugging

  4. Test Locally First: SAM local saves time and AWS costs

  5. Use Infrastructure as Code: SAM templates are reproducible and version-controlled

What's Next?

In Part 4: Event-Driven Architecture with Lambda, we'll explore:

  • Multiple event sources (S3, DynamoDB Streams, SQS)

  • Asynchronous processing patterns

  • Event routing and filtering

  • Building a complete event-driven workflow

We'll expand on this registration system to include email verification and user onboarding!


This article is based on a real user registration system I built and deployed to production.

Last updated