A beginner-friendly AWS Lambda project in Go that makes it easy to manage multiple functions. Each function has its own deployment workflow - just copy and paste to add new functions!
- β Simple: One workflow file per function - easy to understand
- β Independent: Deploy functions separately or together
- β Smart: Only deploys when that function changes
- β Scalable: Add new functions by copying existing ones
- β
Shared Code: Common utilities in
shared/package
vibe-coding-project-lambda/
βββ functions/ # All your Lambda functions
β βββ time-api/ # Function 1: JST time API
β β βββ main.go
β β βββ main_test.go
β βββ hello-world/ # Function 2: Hello world API
β β βββ main.go
β β βββ main_test.go
β βββ receipt-processor/ # Function 3: Receipt OCR processor
β βββ main.go
β βββ main_test.go
βββ shared/ # Shared utilities
β βββ response/ # API response helpers
β βββ response.go
βββ .github/workflows/ # Deployment workflows
β βββ deploy-time-api.yml # Deploys time-api
β βββ deploy-hello-world.yml # Deploys hello-world
β βββ deploy-receipt-processor.yml # Deploys receipt-processor
β βββ _TEMPLATE.yml # Copy this for new functions
βββ scripts/
βββ new-function.sh # Create new function
βββ create-functions.sh # Create functions in AWS
Runtime: All functions use Go with
provided.al2023custom runtime andbootstraphandler
Returns current time in JST timezone.
Test it:
curl https://your-api.com/timeResponse:
{
"message": "Current time in Japan",
"current_time": "2025-10-18 15:30:45",
"timezone": "JST (Asia/Tokyo)",
"timestamp": 1729238445
}Simple hello API with optional name parameter.
Test it:
curl "https://your-api.com/hello?name=Alice"Response:
{
"message": "Hello, Alice!",
"version": "1.0.0",
"timestamp": 1729238445
}Process receipt images with OCR and extract structured data. Stores images in S3 with JST date-based folder organization.
Test it:
# Prepare base64 encoded receipt image
FILE_CONTENT=$(base64 -i receipt.jpg)
# Upload receipt image
curl -X POST "https://your-api.com/receipt" \
-H "Content-Type: application/json" \
-d "{
\"filename\": \"receipt.jpg\",
\"file_content\": \"$FILE_CONTENT\",
\"content_type\": \"image/jpeg\"
}"Response:
{
"success": true,
"message": "File uploaded successfully",
"file_info": {
"file_name": "receipt.jpg",
"bucket_name": "lambda-file-uploads",
"key": "2025-10-18/receipt.jpg",
"size": 45123,
"content_type": "image/jpeg",
"url": "https://lambda-file-uploads.s3.ap-northeast-1.amazonaws.com/2025-10-18/receipt.jpg",
"upload_date": "2025-10-18"
},
"timestamp": 1729238445
}Features:
- β Upload receipt images to S3
- β Automatic S3 bucket creation (if not exists)
- β JST date-based folder structure (YYYY-MM-DD)
- β Base64 encoded file content
- π§ OCR text extraction (coming soon)
- π§ Structured receipt data extraction (coming soon)
Environment Variables:
S3_BUCKET_NAME(optional): Custom bucket name (default:lambda-file-uploads)
make depsmake build-allmake testPush to master branch and the functions will auto-deploy!
Create manually:
mkdir -p functions/user-api
# Add main.go and main_test.goCopy the template:
cp .github/workflows/_TEMPLATE.yml .github/workflows/deploy-user-api.ymlOpen deploy-user-api.yml and replace YOUR-FUNCTION-NAME with user-api (4 places).
That's it! π
The aws-lambda-deploy action will automatically create the Lambda function if it doesn't exist!
git add .
git commit -m "Add user-api function"
git push origin masterGitHub Actions will automatically:
- Build your function
- Create the Lambda function (if it doesn't exist)
- Deploy your code
π That's it!
# Build all functions
make build-all
# Build specific function
make build FUNCTION=time-api
# Test all functions
make test
# Test specific function
make test-function FUNCTION=hello-world
# Create deployment zips
make zip-all # All functions
make zip FUNCTION=time-api # Specific function
# List available functions
make list-functions
# Clean build artifacts
make cleanGo to GitHub β Settings β Secrets and variables β Actions
Add these 4 secrets:
| Secret | Example | Description |
|---|---|---|
AWS_ROLE_ARN |
arn:aws:iam::123456789012:role/GitHubActionsLambdaRole |
IAM role for GitHub Actions deployment |
AWS_REGION |
us-east-1 |
AWS region |
LAMBDA_FUNCTION_PREFIX |
vibe- |
Prefix for function names |
LAMBDA_EXECUTION_ROLE_ARN |
arn:aws:iam::123456789012:role/lambda-execution-role |
IAM role for Lambda function execution |
Note: You need TWO different roles:
- GitHub Actions role (for deployment)
- Lambda execution role (for running functions)
Each function has its own workflow file:
- Triggers automatically when you push changes to that function
- Manual trigger via GitHub Actions tab
- Independent deployment - one function failing doesn't affect others
Example: Change functions/time-api/main.go β Only deploy-time-api.yml runs!
Each workflow file is simple and self-contained:
name: Deploy time-api # 1. Name it clearly
on:
push:
paths:
- 'functions/time-api/**' # 2. Only run when this function changes
- 'shared/**' # Also run if shared code changes
jobs:
deploy:
steps:
- Checkout code
- Setup Go
- Build time-api # 3. Build this specific function
- Configure AWS
- Deploy to Lambda # 4. Deploy to vibe-time-apiBenefits:
- β Easy to read and understand
- β Easy to customize per function
- β No complex matrix or loops
- β Perfect for beginners
Put common utilities in shared/:
// In your function
import "vibe-coding-project-lambda/shared/response"
func Handler(ctx context.Context, request events.APIGatewayProxyRequest) {
// Use shared helpers
return response.Success(200, myData)
return response.Error(500, "Something went wrong")
return response.MethodNotAllowed("GET")
}When you update shared/, all functions that use it will be redeployed automatically!
Check GitHub Actions tab to see the workflow status.
Make sure you set LAMBDA_FUNCTION_PREFIX secret correctly. Function names are: PREFIX + function-name
Example: vibe- + time-api = vibe-time-api
make clean
make deps
make build-allGo to GitHub β Actions β Select workflow β Run workflow
Your Lambda functions automatically write logs to CloudWatch. The lambda-execution-role includes permissions for:
- β Creating log groups
- β Creating log streams
- β Writing log events
# View real-time logs for time-api
aws logs tail /aws/lambda/vibe-time-api --follow
# View logs from last 10 minutes
aws logs tail /aws/lambda/vibe-hello-world --since 10m
# View logs from specific time
aws logs tail /aws/lambda/vibe-time-api --since 2025-10-18T14:00:00- Go to CloudWatch: https://console.aws.amazon.com/cloudwatch/
- Click Logs β Log groups
- Find
/aws/lambda/vibe-time-apior/aws/lambda/vibe-hello-world - Click to view logs and filter by time
Check if the execution role has the correct permissions:
aws iam get-attached-role-policies --role-name lambda-execution-role
# Should show: AWSLambdaBasicExecutionRoleSee AWS_SETUP.md for detailed AWS infrastructure setup including:
- Creating IAM roles
- Setting up OIDC authentication
- Creating Lambda functions
- Configuring API Gateway
- One workflow per function - Keep it simple
- Use the template - Copy
_TEMPLATE.ymlfor new functions - Test locally first - Run
make testbefore pushing - Shared IAM role - All functions use the same role
- Name consistently - Use kebab-case (like
user-api)
- Deploy all functions? Push changes to
shared/- all workflows run! - Deploy one function? Only change that function's directory
- Customize per function? Edit that function's workflow file
- No manual AWS setup needed! The deploy action creates functions automatically
Let's add a "user-api" function from scratch:
# 1. Create function directory and code
mkdir -p functions/user-api
# Add main.go and main_test.go (copy from existing functions)
# 2. Copy workflow template
cp .github/workflows/_TEMPLATE.yml .github/workflows/deploy-user-api.yml
# 3. Replace YOUR-FUNCTION-NAME with user-api
# In your editor: Find "YOUR-FUNCTION-NAME" β Replace with "user-api"
# 4. Test locally
make build FUNCTION=user-api
make test-function FUNCTION=user-api
# 5. Commit and push
git add .
git commit -m "Add user-api function"
git push origin masterDone! GitHub Actions will automatically create the Lambda function and deploy it. π
| File | Purpose |
|---|---|
functions/*/main.go |
Your Lambda function code |
functions/*/main_test.go |
Tests for your function |
shared/response/ |
Helper functions used by all functions |
.github/workflows/deploy-*.yml |
Deployment workflow for each function |
.github/workflows/_TEMPLATE.yml |
Copy this to add new functions |
Makefile |
Build commands |
go.mod |
Go dependencies |
- Fork the repository
- Add your function following the guide above
- Test locally
- Submit a Pull Request
MIT License
Q: Why one workflow per function instead of a matrix?
A: Simpler for beginners! Each workflow is self-contained and easy to understand.
Q: Can I still deploy multiple functions at once?
A: Yes! If you change shared/ or push changes to multiple functions, all their workflows run.
Q: Do I need separate IAM roles?
A: No! All functions share one IAM role with wildcard permissions (vibe-*).
Q: How do I customize a function's deployment?
A: Just edit that function's workflow file. They're independent!
Q: What if I want different Go versions per function?
A: Edit the go-version in that function's workflow file.