Deployment
Belt deploys serverless applications to AWS using Terraform. The CLI wraps
terraform init/plan/apply with conventions for environment management,
Lambda packaging, and pre-deploy backups.
Quick Deploy
belt deploy <env> # init → plan → apply (interactive)
belt deploy prod --auto # skip confirmation prompt
belt deploy prod --skip-backup # skip pre-deploy backup
belt deploy --backup-only # create recovery point without deploying
First-Time Setup
# 1. Create S3 bucket for Terraform state
belt setup state
# 2. Scaffold an environment
belt generate environment dev01
# 3. Generate DynamoDB table definitions from schema
belt setup tables dev01
# 4. Initialize and deploy
belt deploy dev01
Environment Structure
Each environment lives in infrastructure/<env>/:
infrastructure/
├── modules/
│ └── main/ # Shared Terraform module
├── dev01/
│ ├── main.tf # Module reference + provider
│ ├── variables.tf # Variable declarations
│ ├── terraform.tfvars # Environment-specific values
│ ├── backend.tf # S3 state backend
│ └── outputs.tf # Exported values
└── prod/
└── ...
What Gets Deployed
The Conveyor Belt Terraform provider reads your Ruby DSL and creates:
- API Gateway — HTTP API with routes matching your DSL
- Lambda functions — packaged Ruby code (one per
gateway/functionblock) - IAM roles — least-privilege policies for DynamoDB table access
- CloudWatch logs — log groups for each Lambda
- DynamoDB tables — from your schema definition
- Custom domain — if configured (Route53 + ACM certificate)
Lambda Packaging
Belt packages the lambda/ directory plus vendored gems. For path: gems
(local development), Belt materializes them into vendor/cache automatically.
The Lambda entry point is specified in config/lambda/<name>.yml:
handler: lambda/<name>.lambda_handler
runtime: ruby3.3
timeout: 30
memory: 256
environment:
ENVIRONMENT: ${var.environment}
Route Manifests
Before deploying, generate the route manifest used at runtime:
belt routes --namespace api
# → writes lambda/lib/routes/api_routes.rb
This is typically done automatically by belt deploy.
Sidecar Lambda Zips
Conveyor Belt packages Ruby lambdas. Some apps also have standalone
aws_lambda_function resources (Node image processors, Cognito triggers)
whose Terraform uses filename + filebase64sha256 pointing at a zip on disk.
belt deploy, belt plan, and belt apply scan infrastructure/**/*.tf for
those zip paths and build any that are missing (or whose source hash changed):
- Directory with
package.json—npm ciin Docker (linux/amd64, Lambda Node image) so native addons likesharpmatch Lambda, then zip - Plain JS directory — zip the
.js/.mjsfiles
The zip lives next to the source (image-processor/image-processor.zip). This
is the same pre-terraform step Stowzilla's scripts/deploy.sh does for the
image processor. Existing zips with no hash file are left alone.
Docker must be running for Node packages.
Terraform Commands
Belt wraps Terraform with environment awareness:
belt init <env> # terraform init with correct backend
belt plan <env> # terraform plan
belt apply <env> # terraform apply
belt destroy <env> # terraform destroy (careful!)
belt output <env> # terraform output
Or use belt deploy <env> which runs init → plan → apply in sequence.
Pre-Deploy Backups
Configure in infrastructure/<env>/belt.rb:
Belt.configure do |config|
config.backups do
dynamodb :all
retention snapshots: 90
end
end
Backups run automatically before each deploy (DynamoDB snapshots, Cognito
exports, S3 syncs). See belt explain backups for full documentation.
Environment Variables
Set BELT_ENV to avoid typing the environment every time:
export BELT_ENV=dev01
belt deploy # uses BELT_ENV
belt deploy prod # explicit arg wins
Frontend Deployment
For apps with a frontend:
belt deploy frontend <env> # build + deploy all frontends
belt deploy frontend <env> --frontend ops # deploy one named frontend
belt frontend env <env> # generate .env from Terraform outputs
belt frontend list # show configured frontends
The directory is frontend/ by default. Multiple SPAs are declared in
config/frontends.yml — see belt explain frontend. Full belt deploy <env>
deploys every configured frontend after terraform apply.
See Also
belt explain routing— how routes map to infrastructurebelt explain backups— pre-deploy backup configurationbelt doctor— check system dependencies before deploying