# How to Deploy Macro Inc. to a Production Environment: Complete 7-Step Guide

> Deploy Macro Inc. to production in 7 steps. Build Rust, provision AWS, deploy Cloudflare Workers, publish Docker images, and orchestrate with CI/CD. Your complete guide.

- Repository: [Macro/macro](https://github.com/macro-inc/macro)
- Tags: how-to-guide
- Published: 2026-08-20

---

**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](https://github.com/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

```bash

# 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

```bash

# 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)](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

```bash

# 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

```bash

# 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

```bash

# 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`](https://github.com/macro-inc/macro/blob/main/docker/) 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/`](https://github.com/macro-inc/macro/blob/main/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

```bash
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)](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

```bash

# 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:

```bash
npx wrangler deploy --env prod --config wrangler.toml

```

### Service-Specific Deployment Patterns

Each worker service in [`services/`](https://github.com/macro-inc/macro/blob/main/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)](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)](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`](https://github.com/macro-inc/macro/blob/main/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

```bash

# 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)](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

```bash

# 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`](https://github.com/macro-inc/macro/blob/main/deploy_web_app.yml) | Push to `main` (path: `apps/web/**`) | Build SPA → Upload to S3 → Invalidate CloudFront |
| [`deploy_service_generic.yml`](https://github.com/macro-inc/macro/blob/main/deploy_service_generic.yml) | Push to `main` (service directories) | Build Docker image → `pulumi up` → `wrangler deploy` |
| [`release-production.yml`](https://github.com/macro-inc/macro/blob/main/release-production.yml) | Tag `v*` | Multi-arch image publish → Lambda artifact release |

Source: [`.github/workflows/`](https://github.com/macro-inc/macro/blob/main/.github/workflows/)

### Manual Pipeline Execution

Force a deployment without code changes:

```bash

# 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:

1. **Revert infrastructure state**
   ```bash
   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
   ```

2. **Revert worker deployment**
   ```bash
   cd services/lexical-service
   npx wrangler rollback --env prod
   ```

3. **Database recovery** (if schema migration caused issues)
   ```bash
   just restore_db <snapshot-identifier>
   ```

4. **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`, and `just 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 test` and 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)](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:

```bash

# 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:

1. Verify local PostgreSQL is running: `docker ps | grep postgres`
2. Check database connectivity in `.env.dev`
3. Run `just initialize_dbs` to ensure migrations are applied
4. Retry `just prepare_db` with explicit logging: `RUST_LOG=sqlx=debug just prepare_db`

Without successful preparation, release builds will fail in CI.