How to Deploy Macro Inc. to a Production Environment: Complete 7-Step Guide
Deploy Macro Inc. to production by building Rust services with just build, provisioning AWS infrastructure via Pulumi stacks, deploying Cloudflare Workers with wrangler, and publishing Docker images to ECS/Fargate—all orchestrated through CI/CD pipelines.
This guide walks through the end-to-end deployment process for the macro-inc/macro repository, a multi-service platform combining Rust backends, Cloudflare Edge infrastructure, and AWS-native resources. All commands and file paths reference the actual source code implementation.
Prerequisites and Local Environment Setup
Before touching production infrastructure, establish a properly configured local development environment. Macro Inc. uses Nix as its primary toolchain orchestrator and Docker Compose for local database services.
Install the Development Shell
# Enter the Nix development shell (provides Rust, Bun, just, docker, Pulumi, etc.)
nix develop
# Alternative: launch with specific shell
nix develop --command bash
The Nix flake automatically pins compatible versions of all build tools, eliminating version drift between local and CI environments.
Initialize Local Databases
# Start PostgreSQL containers for all required databases
docker compose -f docker/docker-compose-databases.yml up -d postgres
# Generate environment files for all deployment targets
just setup_test_envs
# Run database migrations across all services
just initialize_dbs
These steps populate .env.dev, .env.test, and .env.prod files with connection strings and create the schema for MacroDB, CommsDB, EmailDB, and ContactsDB as referenced in [docker/docker-compose-databases.yml](https://github.com/macro-inc/macro/blob/main/docker/docker-compose-databases.yml).
Build Production Artifacts
Macro Inc. produces three distinct artifact types: Rust binaries (services and Lambdas), Docker images, and Cloudflare Workers. Build all artifacts before any deployment step.
Build Rust Services and Lambda Functions
# Compile all service binaries
just build
# Generate Lambda deployment packages (zip files)
just build_lambdas
The just build command orchestrates cargo build --release across all workspace crates. Lambda functions receive special treatment via the cargo-lambda toolchain, outputting optimized zip archives to target/lambda/.
Prepare SQLx Query Metadata
# Generate offline query metadata required for release builds
just prepare_db
Critical: Macro Inc. does not use SQLx offline mode for tests. The prepare_db command must execute after any schema migration to regenerate .sqlx/ metadata, ensuring compile-time query verification passes in CI.
Build Docker Images
# Example: build the lexical service image
docker build -f docker/lexical-service.Dockerfile -t macro/lexical:prod .
# Build all service images via just
just build_images
Dockerfiles reside in docker/*.Dockerfile with service-specific configurations for multi-stage Rust builds.
Deploy Infrastructure with Pulumi
Macro Inc. manages all AWS infrastructure through Pulumi TypeScript stacks under infra/stacks/. Each stack represents an independently deployable infrastructure component.
Core Production Stacks
| Stack | Purpose | Key Resources |
|---|---|---|
web-app |
Static site hosting | S3 bucket, CloudFront distribution, Route 53 records |
cloud-storage-cache |
Edge caching layer | Docker-based cache services |
fusion-auth |
Authentication service | ECS Fargate, RDS PostgreSQL |
search |
Full-text search | OpenSearch domain, IAM policies |
kafka-cluster |
Event streaming | MSK cluster, topic definitions |
Deploy a Stack to Production
cd infra/stacks/web-app
# Select and deploy the production stack
pulumi up --stack prod
First-time deployment: Pulumi prompts for required secrets (e.g., fusionauth-db-password-prod). Store these in Pulumi's encrypted state or export as environment variables beforehand.
Stack Configuration Management
Each stack maintains environment-specific configuration in Pulumi.<stack>.yaml. The production configuration references:
- Pre-provisioned SSL certificates
- Registered domain names
- VPC and subnet IDs
- Database connection parameters
Consult [infra/README.md](https://github.com/macro-inc/macro/blob/main/infra/README.md) for complete stack documentation and secret management procedures.
Deploy Cloudflare Workers
Real-time services—including document collaboration, WebSocket handling, and sync operations—run as Cloudflare Workers at the network edge.
Deploy via Wrangler CLI
# Navigate to target service
cd services/lexical-service
# Deploy to production environment
bun run deploy-prod
The deploy-prod script wraps wrangler deploy --env prod with additional build steps. Direct wrangler usage:
npx wrangler deploy --env prod --config wrangler.toml
Service-Specific Deployment Patterns
Each worker service in services/ follows identical patterns:
| Service | Deployment Command | Reference |
|---|---|---|
| lexical-service | bun run deploy-prod |
[services/lexical-service/README.md](https://github.com/macro-inc/macro/blob/main/services/lexical-service/README.md) |
| sync-service | npx wrangler deploy --env prod |
[services/sync-service/README.md](https://github.com/macro-inc/macro/blob/main/services/sync-service/README.md) |
| websocket-service | bun run deploy-prod |
Service README |
Worker resources: KV namespaces and Durable Objects provision automatically on first deployment. Verify binding configuration in each service's wrangler.toml.
Deploy Docker-Based Services
Containerized services deploy to ECS Fargate through Pulumi stack updates. The workflow combines image publishing with infrastructure reconciliation.
Publish and Deploy Container Images
# Tag image with version identifier
docker tag macro/lexical:prod registry.example.com/macro/lexical:2024-08-20
# Push to configured registry
docker push registry.example.com/macro/lexical:2024-08-20
# Update stack to reference new image
cd infra/stacks/web-app
pulumi up --stack prod
Pulumi detects the image tag change and performs a rolling deployment of ECS tasks, maintaining service availability throughout the update.
Local Docker Compose vs. Production
The [docker/docker-compose.yml](https://github.com/macro-inc/macro/blob/main/docker/docker-compose.yml) supports local integration testing only. Production containers never use Compose; they execute under AWS ECS with Pulumi-managed task definitions, service discovery, and auto-scaling policies.
Verify Deployment Health
Validate production functionality through comprehensive test execution against live infrastructure.
Run Test Suites
# Execute all Rust unit and integration tests
just test
# Execute end-to-end test suite
just test_e2e
Tests authenticate against production endpoints and verify database connectivity, search indexing, and worker responsiveness. Failure indicates infrastructure misconfiguration or incomplete deployment.
Monitoring and Observability
Deployed stacks automatically emit metrics to CloudWatch. Check the Pulumi stack outputs for:
- CloudFront distribution URLs
- ECS service ARNs
- OpenSearch domain endpoints
- MSK broker connection strings
CI/CD Pipeline Integration
Production deployments typically trigger automatically via GitHub Actions. Understand the pipeline architecture for manual intervention or troubleshooting.
Key Workflows
| Workflow | Trigger | Actions |
|---|---|---|
deploy_web_app.yml |
Push to main (path: apps/web/**) |
Build SPA → Upload to S3 → Invalidate CloudFront |
deploy_service_generic.yml |
Push to main (service directories) |
Build Docker image → pulumi up → wrangler deploy |
release-production.yml |
Tag v* |
Multi-arch image publish → Lambda artifact release |
Source: .github/workflows/
Manual Pipeline Execution
Force a deployment without code changes:
# Trigger via GitHub CLI
gh workflow run deploy_service_generic.yml --ref main
# Or dispatch with specific inputs
gh workflow run deploy_web_app.yml -f environment=prod
Rollback Procedures
When production releases require reversal, execute these steps in sequence:
-
Revert infrastructure state
cd infra/stacks/web-app pulumi destroy --stack prod # removes resources # Or roll back to previous state pulumi stack export --stack prod > backup.json pulumi stack import --stack prod < previous-state.json -
Revert worker deployment
cd services/lexical-service npx wrangler rollback --env prod -
Database recovery (if schema migration caused issues)
just restore_db <snapshot-identifier> -
Emergency hot-fix Push corrective commit to
main; CI automatically redeploys corrected artifacts.
Summary
Deploying Macro Inc. to production requires coordinating multiple build systems and infrastructure providers:
- Local setup with Nix development shell and Docker database services
- Artifact building via
just build,just build_lambdas, andjust prepare_db - Infrastructure provisioning through Pulumi stacks (
pulumi up --stack prod) - Edge deployment with wrangler for Cloudflare Workers
- Container publishing and ECS updates for Docker-based services
- Verification through
just testand end-to-end suites - Automation via GitHub Actions with manual rollback capabilities
Each phase references specific files in the repository—consult the linked documentation for environment-specific configurations.
Frequently Asked Questions
What permissions are required to deploy Macro Inc. to production?
You need AWS credentials with permissions for S3, CloudFront, Route 53, ECS, RDS, MSK, and OpenSearch; Pulumi access to the organization stack; Cloudflare API tokens for worker deployment; and Docker registry push access. The [infra/README.md](https://github.com/macro-inc/macro/blob/main/infra/README.md) specifies exact IAM policies and token scopes.
Can I deploy Macro Inc. without using Pulumi?
No. Pulumi is the sole infrastructure-as-code tool in the repository. All AWS resources—VPCs, databases, caches, and compute—are defined in TypeScript stacks under infra/stacks/. Manual resource creation will cause drift and break subsequent deployments.
How do I deploy a single service without rebuilding everything?
Use targeted just commands and stack selection:
# Build only lexical-service
cargo build --release -p lexical-service
# Deploy only its worker
cd services/lexical-service && bun run deploy-prod
# Update only the ECS service (if containerized)
cd infra/stacks/cloud-storage-cache && pulumi up --stack prod
Pulumi performs differential updates, modifying only changed resources.
What happens if just prepare_db fails during deployment?
SQLx compile-time verification requires accurate query metadata. If prepare_db fails:
- Verify local PostgreSQL is running:
docker ps | grep postgres - Check database connectivity in
.env.dev - Run
just initialize_dbsto ensure migrations are applied - Retry
just prepare_dbwith explicit logging:RUST_LOG=sqlx=debug just prepare_db
Without successful preparation, release builds will fail in CI.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →