Skip to content

Repository files navigation

AWS Lambda Universal Template# AWS Lambda Microservice Example

**A production-ready, configuration-driven Lambda template that works with any upstream service (API Gateway, Tyk Gateway, EventBridge, SQS) and integrates with any downstream AWS service (DynamoDB, S3, SQS, SNS, and more).**This repository contains a simple AWS Lambda microservice implemented in

Python. It demonstrates how to use some of the essential and advanced

πŸ’‘ New to AWS Lambda? Check out UNDER_THE_HOOD.md for a beginner-friendly explanation of how everything works!features of AWS Lambda while keeping the code and infrastructure

definition clear and maintainable. The project uses a custom

---template generator (written in Python) to produce a CloudFormation

template at build time.

🎯 What Is This?

Features

Instead of writing Lambda functions from scratch every time, this template lets you:

  • Environment variables and configuration: The Lambda handler reads
  1. Configure what you need in a YAML file (config.yaml) greeting parameters and secret configuration from environment

  2. Write your business logic in Python (handler.py) variables. This decouples configuration from code and allows

  3. Generate infrastructure code automatically different values per environment without redeploying. Concurrency

  4. Deploy to AWS in minutes Labs recommends using versions, aliases and environment variables to

manage configuration across stages【380550635739302†L52-L83】.

No need to manually write IAM policies, CloudFormation resources, or integration code!- Lambda layer: A separate layer contains a shared reverse_string

helper. Layers promote code reuse and keep the main function

--- package small【989117450241150†L296-L297】.

  • Reserved concurrency: The function reserves a fixed number of

✨ What Can It Do? concurrent executions (configured to 5) to avoid exhausting the

account’s concurrency limit and to guarantee availability when other

Connect to Anything (Upstream) workloads compete for resources【989117450241150†L305-L311】.

  • βœ… API Gateway - Build REST APIs- Versioning and aliases: The generated CloudFormation template

  • βœ… Lambda Function URL - Connect to Tyk Gateway or any external gateway publishes a version of the function and creates a prod alias

  • βœ… EventBridge - Event-driven architectures pointing to it. Aliases abstract function versions and are the

  • βœ… SQS - Process queues recommended way to implement canary or blue‑green deployments

  • βœ… Direct Calls - Invoke from other services 【121160137832048†L316-L376】.

  • Secrets Manager integration: The handler optionally retrieves a

Integrate with Any AWS Service (Downstream) secret from AWS Secrets Manager if SECRETS_ENABLED=true and

  • βœ… DynamoDB - NoSQL database (auto-creates tables!) SECRET_NAME are set. To keep costs down the secret value is

  • βœ… S3 - File storage (auto-creates buckets!) cached between invocations as suggested by Concurrency Labs【380550635739302†L52-L83】.

  • βœ… SQS - Message queues

  • βœ… SNS - Notifications## Repository structure

  • βœ… Secrets Manager - Secure secret storage

  • βœ… RDS - Relational databases- lambda_function/handler.py – The Lambda handler implementing the

    microservice logic.

Production Features Built-In- layer/python/utils.py – Utility module packaged as a Lambda layer.

  • βœ… Monitoring - CloudWatch Logs, Metrics, Alarms- generate_template.py – Script that reads the handler and layer

  • βœ… Tracing - X-Ray distributed tracing sources and produces a CloudFormation template (template.yaml).

  • βœ… Error Handling - Automatic error logging and alerting- tests/ – Pytest-based unit tests that exercise the handler logic

  • βœ… Cost Control - Concurrency limits, efficient caching locally.

  • βœ… Security - Auto-generated IAM policies with least-privilege access

Prerequisites


To run the code and tests locally you need PythonΒ 3.11 or newer. No

πŸš€ Quick Start (5 Minutes)external dependencies are required for the microservice itself; the

tests depend on pytest.

Step 1: Install Dependencies


pip install pyyaml boto3

```Run the generator script from the project root:



### Step 2: Choose a Template```bash

Pick the example that matches your use case:python generate_template.py

# For a REST API with DynamoDBThis will produce `template.yaml` in the same directory.  The

cp examples/rest-api.yaml config.yamltemplate is fully self‑contained and can be deployed to AWS via the

AWS Console, AWS CLI (`aws cloudformation deploy`) or the CDK

# For Tyk Gateway integrationbootstrap process.

cp examples/tyk-integration.yaml config.yaml

```## Running locally



### Step 3: Customize Your ProjectAlthough this Lambda is designed for AWS, you can invoke the handler

Edit `config.yaml` and change the project name:locally for rapid testing.  For example:

```yaml

project:```python

  name: my-awesome-api  # ← Change this!from lambda_function.handler import handler

  environment: dev

```event = {"name": "World", "numbers": [1, 2, 3]}

response = handler(event, None)

### Step 4: Generate Infrastructureprint(response)

```bash```

python3 generate_advanced_template.py

```If you wish to simulate Secrets Manager retrieval locally, set the

This creates `template.yaml` with all your AWS resources!environment variables `SECRETS_ENABLED=false` and `SECRET_VALUE` to a

desired value before invoking the handler.

### Step 5: Deploy

```bash## Testing

aws cloudformation deploy \

  --template-file template.yaml \Install `pytest` (if not already installed) and run the tests:

  --stack-name my-awesome-api-stack \

  --capabilities CAPABILITY_IAM```bash

```pip install pytest

pytest -q

### Step 6: Test```

```bash

# Get your API URLThe tests cover default behaviour, summing arrays of numbers, reading

aws cloudformation describe-stacks \custom environment variables and falling back to a local secret when

  --stack-name my-awesome-api-stack \Secrets Manager is disabled.

  --query 'Stacks[0].Outputs'

# Test it!
curl https://your-api-url.amazonaws.com/prod

Done! πŸŽ‰ You now have a production-ready Lambda with monitoring and integrations!


πŸ“ Common Use Cases

Example 1: REST API with Database

What you want: A REST API that stores data in DynamoDB

Configure (config.yaml):

project:
  name: user-api
  environment: dev

upstream:
  type: apigateway     # Creates API Gateway
  api_gateway:
    enabled: true

downstream:
  dynamodb:
    enabled: true
    create_table: true  # Auto-creates table!
    partition_key: user_id

Code (lambda_function/handler.py):

from base_handler import BaseLambdaHandler
import uuid

class MyAPIHandler(BaseLambdaHandler):
    def process(self, event, context):
        method = event.get('httpMethod')
        
        if method == 'POST':
            # Create user
            body = self._parse_api_gateway_body(event)
            
            self.put_dynamodb_item({
                'user_id': str(uuid.uuid4()),
                'name': body['name'],
                'email': body['email']
            })
            
            return {
                'statusCode': 201,
                'body': {'message': 'User created'}
            }
        
        elif method == 'GET':
            # Get user
            user_id = event['pathParameters']['id']
            user = self.get_dynamodb_item({'user_id': user_id})
            
            if not user:
                return {'statusCode': 404, 'body': {'error': 'Not found'}}
            
            return {'statusCode': 200, 'body': user}

Deploy:

python3 generate_advanced_template.py
aws cloudformation deploy --template-file template.yaml \
  --stack-name user-api-stack --capabilities CAPABILITY_IAM

Example 2: Tyk Gateway Integration

What you want: Connect your Lambda to Tyk Gateway (or any external API gateway)

Configure (config.yaml):

project:
  name: public-api
  environment: prod

upstream:
  type: http          # Use Function URL instead of API Gateway
  function_url:
    enabled: true
    auth_type: NONE   # Tyk handles authentication
    cors:
      allow_origins: ["https://yourdomain.com"]

downstream:
  dynamodb:
    enabled: true
    create_table: true
  secrets_manager:
    enabled: true
    secret_name: "api-keys"

Deploy and Get URL:

python3 generate_advanced_template.py
aws cloudformation deploy --template-file template.yaml \
  --stack-name public-api-stack --capabilities CAPABILITY_IAM

# Get the Function URL
aws cloudformation describe-stacks \
  --stack-name public-api-stack \
  --query 'Stacks[0].Outputs[?OutputKey==`FunctionUrl`].OutputValue' \
  --output text

Configure Tyk: Point Tyk to your Lambda Function URL and you're done!

Example 3: Scheduled Job

What you want: Run a task every hour (like sending reports)

Configure (config.yaml):

project:
  name: daily-report

upstream:
  type: eventbridge
  eventbridge:
    enabled: true
    schedule_expression: "rate(1 hour)"  # Or use cron

downstream:
  s3:
    enabled: true
    create_bucket: true
  sns:
    enabled: true
    create_topic: true

Code:

class ReportHandler(BaseLambdaHandler):
    def process(self, event, context):
        # Generate report
        report = self.generate_report()
        
        # Save to S3
        self.upload_to_s3(
            report.encode('utf-8'),
            f"reports/{self.correlation_id}.pdf"
        )
        
        # Send notification
        self.publish_sns_message(
            f"Report generated: {self.correlation_id}",
            subject="Daily Report"
        )
        
        return {'statusCode': 200}

βš™οΈ Configuration Guide

The config.yaml file controls everything. Here are the main sections:

Project Settings

project:
  name: my-service          # Your service name
  description: "My API"     # Description
  environment: dev          # dev, staging, or prod

Lambda Settings

lambda:
  runtime: python3.11       # Python version
  timeout: 30               # Maximum runtime in seconds
  memory_size: 256          # Memory in MB
  architectures: x86_64     # x86_64 or arm64

Upstream (How Requests Come In)

Option 1: API Gateway (Traditional REST API)

upstream:
  type: apigateway
  api_gateway:
    enabled: true
    enable_cors: true
    throttle_rate_limit: 1000

Option 2: Function URL (For Tyk or External Gateways)

upstream:
  type: http
  function_url:
    enabled: true
    auth_type: NONE         # Or AWS_IAM
    cors:
      allow_origins: ["*"]

Option 3: EventBridge (Events or Scheduled)

upstream:
  type: eventbridge
  eventbridge:
    enabled: true
    schedule_expression: "rate(5 minutes)"

Option 4: SQS Queue

upstream:
  type: sqs
  sqs:
    enabled: true
    batch_size: 10

Downstream (Services Your Lambda Uses)

DynamoDB (Database)

downstream:
  dynamodb:
    enabled: true
    create_table: true      # Automatically creates table
    partition_key: id       # Primary key

S3 (File Storage)

downstream:
  s3:
    enabled: true
    create_bucket: true     # Automatically creates bucket
    enable_encryption: true

SQS (Send Messages)

downstream:
  sqs:
    enabled: true
    create_queue: true

SNS (Notifications)

downstream:
  sns:
    enabled: true
    create_topic: true

Secrets Manager

downstream:
  secrets_manager:
    enabled: true
    secret_name: "my-api-keys"

Monitoring

observability:
  xray:
    enabled: true           # Distributed tracing
  cloudwatch:
    log_retention_days: 7
  alarms:
    enabled: true           # Auto-create alarms
    error_threshold: 5

πŸ’» Helper Methods

When you extend BaseLambdaHandler, you get easy-to-use helper methods:

Database (DynamoDB)

# Save data
self.put_dynamodb_item({'id': '123', 'name': 'John'})

# Get data
item = self.get_dynamodb_item({'id': '123'})

File Storage (S3)

# Upload file
self.upload_to_s3(data, 'folder/file.json')

# Download file
data = self.get_from_s3('folder/file.json')

Messaging (SQS)

# Send message
self.send_sqs_message('{"action": "process"}')

Notifications (SNS)

# Send notification
self.publish_sns_message('Alert!', subject='Warning')

Secrets

# Get secret (automatically cached)
api_key = self.get_secret('my-api-key')

Metrics

# Track custom metrics
self.publish_custom_metric('ItemsProcessed', 1.0)

πŸ› οΈ Useful Commands

# Install everything
make install

# Run tests
make test

# Generate CloudFormation template
make generate
# Or: python3 generate_advanced_template.py

# Deploy to AWS
make deploy

# View logs (real-time)
aws logs tail /aws/lambda/my-service-dev --follow

# Test locally
python3 -c "
from lambda_function.handler import handler
response = handler({'name': 'Test'}, None)
print(response)
"

🌍 Multiple Environments

Create separate configs for dev, staging, and prod:

# Create environment-specific configs
cp config.yaml config-dev.yaml
cp config.yaml config-staging.yaml
cp config.yaml config-prod.yaml

# Edit each to set: environment: dev/staging/prod

# Deploy to each
cp config-dev.yaml config.yaml && make deploy
cp config-staging.yaml config.yaml && make deploy
cp config-prod.yaml config.yaml && make deploy

πŸ› Troubleshooting

"Template generation fails"

pip install pyyaml boto3

"Deployment fails with IAM errors"

Make sure to include --capabilities CAPABILITY_IAM:

aws cloudformation deploy \
  --template-file template.yaml \
  --stack-name my-stack \
  --capabilities CAPABILITY_IAM

"Lambda can't access DynamoDB"

  • Check that DynamoDB is enabled in config.yaml
  • Verify the table was created: Check AWS Console > DynamoDB
  • Check CloudWatch Logs for specific errors

"How do I see logs?"

# Real-time logs
aws logs tail /aws/lambda/my-function-name --follow

# Search for errors
aws logs filter-log-events \
  --log-group-name /aws/lambda/my-function-name \
  --filter-pattern "ERROR"

"Function times out"

  • Increase timeout in config.yaml (default is 30 seconds)
  • Check CloudWatch X-Ray traces to see where time is spent
  • Make sure your database queries are efficient

πŸ“ What's in This Repository?

lambda-template/
β”œβ”€β”€ config.yaml                      # ← Configure everything here
β”œβ”€β”€ generate_advanced_template.py   # ← Generates CloudFormation
β”œβ”€β”€ template.yaml                    # Generated AWS infrastructure
β”‚
β”œβ”€β”€ lambda_function/
β”‚   β”œβ”€β”€ handler.py                  # ← Write your code here
β”‚   β”œβ”€β”€ base_handler.py             # Framework (don't edit)
β”‚   └── __init__.py
β”‚
β”œβ”€β”€ layer/
β”‚   └── python/
β”‚       └── utils.py                # Shared utilities
β”‚
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_advanced_handler.py    # Tests
β”‚   └── events/                     # Sample API Gateway/SQS events
β”‚
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ rest-api.yaml               # Example: REST API
β”‚   └── tyk-integration.yaml        # Example: Tyk Gateway
β”‚
β”œβ”€β”€ Makefile                         # Quick commands
β”œβ”€β”€ requirements.txt                 # Python dependencies
β”œβ”€β”€ README.md                        # ← You are here
└── UNDER_THE_HOOD.md               # Technical deep-dive

πŸŽ“ Learn More


πŸ’‘ Tips & Best Practices

  1. Start simple - Use an example config, then add features as needed
  2. Test locally first - Use make test before deploying
  3. Enable X-Ray - Helps debug performance issues
  4. Use CloudWatch Alarms - Get notified when errors happen
  5. Never hardcode secrets - Use Secrets Manager
  6. Use correlation IDs - Track requests across services (built-in!)
  7. Set appropriate timeouts - Don't pay for runaway functions
  8. Monitor costs - Check AWS CloudWatch billing alerts

❓ Common Questions

Q: Do I need to know CloudFormation? A: No! The template generates it for you.

Q: Can I use this with Tyk Gateway? A: Yes! Use upstream.type: http with function_url.enabled: true

Q: How much does this cost? A: AWS Lambda free tier includes 1M requests/month. After that, it's pay-per-use.

Q: Can I customize the generated template? A: Yes, but it's better to add to config.yaml so it's reproducible.

Q: Is this production-ready? A: Yes! Includes monitoring, alarms, error handling, and security best practices.

Q: Can I use other programming languages? A: The framework is Python, but you can modify it for Node.js, Go, etc.


πŸŽ‰ You're All Set!

This template handles the infrastructure so you can focus on your business logic.

Next Steps:

  1. Try the Quick Start above
  2. Read UNDER_THE_HOOD.md to understand how it works
  3. Check out examples in the examples/ folder
  4. Customize config.yaml for your needs
  5. Deploy and build something awesome!

Happy coding! πŸš€


πŸ“„ License

MIT License - Use this for any project!

About

Python Lambda template

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages