Skip to content

Terraform (AWS)

The AWS deployment is managed by Terraform files in deploy/terraform/. The stack includes DynamoDB, 5 Lambda functions, a Step Function state machine, SNS for alerts, and EventBridge for scheduling.

Prerequisites

  • Terraform 1.5+
  • AWS CLI v2 configured with appropriate credentials
  • Go 1.24+ (to build Lambda binaries)

Bootstrap State Backend

Before the first deploy, create the S3 bucket and DynamoDB table for Terraform state:

cd deploy/terraform/bootstrap
terraform init
terraform apply

This creates:

  • S3 bucket for .tfstate files
  • DynamoDB table for state locking

Build Lambda Binaries

make build-lambda

This runs deploy/build.sh, which cross-compiles all 5 Lambda handlers for linux/amd64 and packages them as zip archives.

Configure Variables

Create a terraform.tfvars file (or use -var flags):

project_name = "my-interlock"
aws_region   = "us-east-1"

# DynamoDB
table_name    = "my-interlock"
readiness_ttl = "1h"
retention_ttl = "168h"

# SNS
sns_topic_name = "my-interlock-alerts"

# Lambda
lambda_memory  = 256
lambda_timeout = 60

# Evaluator API (for HTTP evaluator runner)
evaluator_base_url = "https://api.example.com"

# Archetype directory (bundled in Lambda zip)
archetype_dir = "/var/task/archetypes"

# S3 data bucket (for trigger artifacts)
data_bucket_name = "my-interlock-data"

Key Variables

VariableTypeDefaultDescription
project_namestringPrefix for all resource names
aws_regionstringAWS region
table_namestringDynamoDB table name
readiness_ttlstring1hTrait readiness cache TTL
retention_ttlstring168hData retention TTL
sns_topic_namestringSNS topic for alerts
lambda_memorynumber256Lambda memory (MB)
lambda_timeoutnumber60Lambda timeout (seconds)
evaluator_base_urlstring""HTTP evaluator base URL
archetype_dirstring/var/task/archetypesArchetype YAML directory in Lambda

Deploy

cd deploy/terraform
terraform init
terraform plan
terraform apply

What Gets Created

ResourceDescription
DynamoDB tableSingle-table with TTL on expiresAt, GSI1 for list queries
DynamoDB StreamTriggers stream-router Lambda on MARKER# writes
5 Lambda functionsstream-router, evaluator, orchestrator, trigger, run-checker
Lambda layersShared dependencies (Python requests for Python Lambdas)
Step Function47-state machine orchestrating the full pipeline lifecycle
SNS topicAlert delivery
EventBridge rulesScheduled MARKER writes to trigger pipeline evaluation
IAM rolesLeast-privilege policies for each Lambda
CloudWatch Log GroupsPer-Lambda log groups

Resource Architecture

The Terraform uses for_each for the core Lambda functions (evaluator, orchestrator, trigger, run-checker), keeping the configuration DRY. The stream-router is defined separately because it has a unique DynamoDB Stream event source mapping.

The Step Function ASL template uses templatefile() to substitute Lambda ARNs:

resource "aws_sfn_state_machine" "pipeline" {
  definition = templatefile("${path.module}/../statemachine.asl.json", {
    OrchestratorFunctionArn = aws_lambda_function.go["orchestrator"].arn
    EvaluatorFunctionArn    = aws_lambda_function.go["evaluator"].arn
    TriggerFunctionArn      = aws_lambda_function.go["trigger"].arn
    RunCheckerFunctionArn   = aws_lambda_function.go["run-checker"].arn
  })
}

IAM

All IAM roles and policies are centralized in iam.tf:

  • Each Lambda gets its own execution role
  • DynamoDB access is scoped to the specific table
  • SNS publish is scoped to the alert topic
  • Step Functions has permission to invoke all 4 downstream Lambdas
  • stream-router has permission to start Step Function executions

Tear Down

cd deploy/terraform
terraform destroy

To also remove the state backend:

cd deploy/terraform/bootstrap
terraform destroy