DB Init Lambda
Database initialization Lambda function for creating PostgreSQL databases and users required by Temporal.
Why This Exists
Temporal requires two PostgreSQL databases:
temporal- Main storage for workflow state, history, and metadatatemporal_visibility- Search and query optimization database
Creating these manually is error-prone and doesn't fit into infrastructure-as-code workflows. The DB Init Lambda:
- Automates database creation during Terraform deployment
- Is idempotent - safe to run multiple times
- Handles permissions - creates user with appropriate grants
- Runs in VPC - secure access to RDS in private subnets
How It Works
Terraform Deployment
│
▼
┌───────────────────┐
│ aws_lambda_ │
│ invocation │
│ (db_init) │
└─────────┬─────────┘
│
▼
┌───────────────────┐ ┌───────────────────┐
│ DB Init Lambda │─────▶│ RDS PostgreSQL │
│ │ │ │
│ 1. Get master │ │ Creates: │
│ creds from SM │ │ - temporal DB │
│ 2. Connect to RDS │ │ - temporal_vis DB │
│ 3. Create DBs │ │ - temporal user │
│ 4. Grant perms │ │ │
└───────────────────┘ └───────────────────┘
Features
| Feature | Description |
|---|---|
| Idempotent | Safe to run multiple times - checks if resources exist |
| Automatic user creation | Creates temporal user with appropriate permissions |
| Schema permissions | Grants full permissions on public schema |
| VPC deployment | Runs in private subnets with RDS access |
| Secrets Manager integration | Retrieves master credentials securely |
Environment Variables
| Variable | Description |
|---|---|
RDS_ENDPOINT | RDS instance endpoint (host:port format) |
RDS_SECRET_ARN | ARN of Secrets Manager secret with master credentials |
DATABASE_NAME | Name of main database to create (default: temporal) |
DATABASE_USER | Name of user to create (default: temporal) |
Invocation
Automatic (via Terraform)
The Lambda is invoked automatically during Temporal deployment:
data "aws_lambda_invocation" "db_init" {
function_name = var.db_init_lambda_arn
input = jsonencode({ action = "initialize" })
}
Manual
aws lambda invoke \
--function-name docustack-dev-db-init \
--region us-east-1 \
/tmp/response.json
cat /tmp/response.json
What Gets Created
Databases
| Database | Purpose |
|---|---|
temporal | Main workflow state, history, metadata |
temporal_visibility | Search and query optimization |
User
| User | Permissions |
|---|---|
temporal | Full access to both databases, public schema |
Dependencies
The Lambda includes pre-bundled dependencies for Lambda compatibility:
psycopg2-binary==2.9.9- PostgreSQL adapter with native libraries
Deployment
Deployed via the db-init-lambda Terraform module:
module "db_init" {
source = "../../modules/db-init-lambda"
name = "docustack-${var.environment}"
environment = var.environment
vpc_id = module.vpc.vpc_id
private_subnet_ids = module.vpc.private_subnet_ids
rds_endpoint = module.rds.endpoint
rds_secret_arn = module.rds.master_secret_arn
rds_security_group_id = module.rds.security_group_id
}
Development Workflow
Local Testing
Local testing requires network access to RDS, which typically means:
- Use a bastion - Connect via SSM port forwarding
- Use VPN - If your VPC has VPN access configured
cd docustack-mono/services/lambdas/db-init
# Install dependencies
pip install psycopg2-binary boto3
# Set environment variables
export RDS_ENDPOINT="localhost:5432" # Via port forwarding
export RDS_SECRET_ARN="arn:aws:secretsmanager:..."
export DATABASE_NAME="temporal"
export DATABASE_USER="temporal"
# Test locally
python -c "from handler import lambda_handler; lambda_handler({}, None)"
Testing in AWS
# Invoke the Lambda
aws lambda invoke \
--function-name docustack-dev-db-init \
--region us-east-1 \
/tmp/response.json
cat /tmp/response.json
# Check logs
aws logs tail /aws/lambda/docustack-dev-db-init \
--region us-east-1 \
--since 10m
Troubleshooting
Connection timeout
- Verify Lambda is in the same VPC as RDS
- Check security group allows Lambda to connect to RDS (port 5432)
- Verify Lambda has route to RDS subnet
Permission denied
- Check RDS master credentials in Secrets Manager
- Verify secret ARN is correct
- Check Lambda IAM role has
secretsmanager:GetSecretValuepermission
Database already exists
This is expected on subsequent runs - the Lambda is idempotent and will skip creation if the database exists.
User already exists
Same as above - the Lambda checks for existing users before creating.
Code Location
docustack-mono/services/lambdas/db-init/
├── handler.py # Main Lambda handler
├── psycopg2/ # Pre-bundled PostgreSQL adapter
└── README.md
Related Documentation
- Database & Workflows - Temporal and DB Init module documentation
- Core Infrastructure - RDS module documentation
- Deployment Guide - How to deploy infrastructure