Skip to content

deployment patterns

Aleksej Komnenovic edited this page Jun 30, 2026 · 3 revisions

Deployment Patterns

Five deployment topologies. Example code in aws/examples/.

Pattern 1: Full Stack

Directory: aws/examples/full-stack/

Deploys everything: VPC + Database + Storage + BRMS + Agent

flowchart TD
    subgraph VPC["VPC (created)"]
        subgraph Public[Public Subnets]
            ALBs[ALBs]
        end
        subgraph Private[Private Subnets]
            BRMS[BRMS ECS Service]
            Agent[Agent ECS Service]
            Aurora[Aurora PostgreSQL]
        end
        ALBs --> BRMS
        ALBs --> Agent
    end
    S3[S3 Bucket\nrules storage]
Loading

When to use

  • Single-account deployments
  • Complete self-contained environments
  • Development and testing

Key configuration

  • vpc.create = true
  • storage != null
  • database != null (provide min/max capacity)
  • brms != null (provide cpu, memory, domain)
  • agent != null (provide cpu, memory)

Pattern 2: Agent Only

Directory: aws/examples/agent-only/

Stateless rule execution: no database, no BRMS.

flowchart TD
    subgraph VPC["VPC (created)"]
        subgraph Public[Public Subnets]
            ALB[Agent ALB]
        end
        subgraph Private[Private Subnets]
            Agent[Agent ECS Service]
        end
        ALB --> Agent
    end
    S3[S3 Bucket\nrules storage, read-only]
Loading

When to use

  • Dedicated rule execution environments
  • High-throughput stateless processing
  • Part of multi-environment setup

Key configuration

  • database = null
  • brms = null
  • agent != null
  • Agent gets read-only S3 access via IAM Architecture

Pattern 3: Existing VPC

Directory: aws/examples/existing-vpc/

Integrate with an already-provisioned VPC.

flowchart TD
    subgraph VPC["Existing VPC (not managed)"]
        subgraph Public[Existing Public Subnets]
            ALBs[ALBs]
        end
        subgraph Private[Existing Private Subnets]
            BRMS[BRMS ECS Service]
            Agent[Agent ECS Service]
            Aurora[Aurora PostgreSQL]
        end
        ALBs --> BRMS
        ALBs --> Agent
    end
    S3[S3 Bucket\nrules storage]
Loading

When to use

  • Enterprise environments with centralized networking
  • Shared VPCs managed by a platform team
  • Compliance requirements for network topology

Key configuration

vpc = {
  create             = false
  id                 = "vpc-0abc123..."
  private_subnet_ids = ["subnet-0aaa...", "subnet-0bbb..."]
  public_subnet_ids  = ["subnet-0ccc...", "subnet-0ddd..."]
}

Validation in Root Module ensures id + both subnet lists are provided.

Pattern 4: Multi-Environment

Directory: aws/examples/multi-environment/

Cross-account deployment with centralized BRMS and distributed Agents.

flowchart LR
    subgraph Mgmt[Management Account]
        BRMS[BRMS]
        DB[Database]
        S3Mgmt[S3 Bucket\ncross-account write access]
    end
    subgraph Staging[Staging Account]
        AgentStg[Agent]
        S3Stg[S3\nread from mgmt bucket]
    end
    subgraph Prod[Production Account]
        AgentProd[Agent]
        S3Prod[S3\nread from mgmt bucket]
    end
    S3Mgmt --> S3Stg
    S3Mgmt --> S3Prod
Loading

Deployment Order (Critical)

  1. Staging first: creates Agent infrastructure
  2. Production second: creates Agent infrastructure
  3. Management last: creates BRMS + DB + S3 with cross-account policies

This order matters because cross-account S3 policies must reference existing account IDs/roles.

Cross-Account S3

Management account S3 bucket grants access to staging/prod:

storage = {
  cross_account_write_principals = [
    "111111111111",  # Staging account
    "222222222222"   # Production account
  ]
}

See Storage Module for how the bucket policy is constructed.

Agents read from management S3

# In staging/prod accounts:
storage = {
  create_bucket        = false
  existing_bucket_arn  = "arn:aws:s3:::gorules-mgmt-rules-abc123"
  existing_bucket_name = "gorules-mgmt-rules-abc123"
}

Pattern 5: Internal / Private (no public subnets)

Directory: aws/examples/internal-alb/

Both load balancers use the internal scheme in private subnets. Nothing is created in a public subnet. Use this when policy forbids public-subnet resources, or when the services are reached only from inside the network.

flowchart TD
    Clients((Internal network))
    License[[portal.gorules.io]]
    subgraph VPC["VPC (module creates nothing public)"]
        subgraph Private[Private Subnets]
            ALBs[Internal ALBs]
            BRMS[BRMS ECS Service]
            Agent[Agent ECS Service]
            Aurora[Aurora PostgreSQL]
        end
    end
    Egress[Your egress: NAT / TGW / proxy]
    Clients --> ALBs
    ALBs --> BRMS
    ALBs --> Agent
    BRMS --> Egress --> License
    BRMS --> S3[S3 Bucket]
    Agent --> S3
Loading

When to use

  • Company policy forbids resources in public subnets
  • Services reached only from inside the network
  • Public ingress is layered on separately, for example CloudFront with a VPC origin

BRMS needs egress

BRMS validates its license at https://portal.gorules.io, so a VPC with no egress cannot run BRMS. The Agent is self-contained. This pattern brings a VPC whose egress comes from your network, and the module creates nothing in a public subnet.

Key configuration

vpc = {
  create             = false # bring a VPC that already has egress
  id                 = "vpc-0123456789abcdef0"
  private_subnet_ids = ["subnet-aaa", "subnet-bbb"]
  public_subnet_ids  = []
}

brms  = { alb_internal = true, /* ... */ }
agent = { alb_internal = true, /* ... */ }

A fully air-gapped, module-built VPC (create = true, nat_gateway_mode = "none") has no internet egress, so it suits an agent-only deployment. See the internal-alb example and the Internal Load Balancers section of the module README.

Auth Mode Combinations

Different security postures are possible:

Component Mode 1 (Simple) Mode 2 (IAM-Native)
Database auth = "secrets" auth = "iam"
Storage auth = "iam" auth = "iam"
BRMS Secrets type = "env" type = "aws-kms"

See Secrets Management for details on each mode.

Clone this wiki locally