> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fjall.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Compute Factory

> Create AWS ECS, Lambda, and EC2 compute resources with the Fjall ComputeFactory pattern.

## Overview

The `ComputeFactory` is Fjall's pattern for creating compute resources. It provides a unified interface to deploy different compute types including ECS containers, EC2 instances, and Lambda functions.

## Basic Usage

```typescript theme={null}
import { App, ComputeFactory } from "@fjall/components-infrastructure";

const app = App.getApp("myapp");

app.addCompute(
  ComputeFactory.build("MyCompute", {
    type: "ecs",
    services: [
      {
        name: "web",
        capacityProvider: "FARGATE",
        cpu: 256,
        memoryLimitMiB: 512,
      },
    ],
  }),
);
```

## Compute Types

### ECS (Elastic Container Service)

Deploy containerised applications with three variants:

#### Fargate (Recommended)

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("MyService", {
    type: "ecs",
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        cpu: 512,
        memoryLimitMiB: 1024,
        desiredCount: 2,
      },
    ],
  }),
);
```

#### Fargate Spot (Cost Savings)

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("BatchProcessor", {
    type: "ecs",
    services: [
      {
        name: "worker",
        capacityProvider: "FARGATE_SPOT",
        cpu: 256,
        memoryLimitMiB: 512,
        // Up to 70% cost savings
      },
    ],
  }),
);
```

#### EC2-backed ECS

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("DevService", {
    type: "ecs",
    services: [
      {
        name: "dev",
        capacityProvider: "EC2",
        cpu: 256,
        memoryLimitMiB: 512,
      },
    ],
  }),
);
```

### Lambda Functions

Deploy serverless functions with code deployment:

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("MyFunction", {
    type: "lambda",
    deployment: "code", // Required discriminator
    handler: "index.handler",
    memorySize: 512,
    timeout: 30,
  }),
);
```

With container images:

```typescript theme={null}
import { Repository } from "aws-cdk-lib/aws-ecr";

// Reference an existing ECR repository
const ecrRepo = Repository.fromRepositoryName(scope, "FunctionRepo", "my-repo");

app.addCompute(
  ComputeFactory.build("ContainerFunction", {
    type: "lambda",
    deployment: "container", // Required discriminator
    ecrRepository: ecrRepo, // Required for container deployment
    memorySize: 1024,
  }),
);
```

<Note>
  Container-based Lambdas require an ECR repository. The `ecrRepository` parameter is required when `deployment: "container"`. When using Fjall's App scaffolding, ECR repositories are created automatically.
</Note>

### EC2 Instances

Deploy traditional virtual machines:

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("MyInstance", {
    type: "ec2",
    instanceType: "t4g.micro",
    ssh: {},
    minCapacity: 1,
    maxCapacity: 3,
  }),
);
```

## Configuration Parameters

### Common Parameters

| Parameter | Type                         | Description        | Default         |
| --------- | ---------------------------- | ------------------ | --------------- |
| `type`    | `"ecs" \| "lambda" \| "ec2"` | Compute type       | `"ecs"`         |
| `vpc`     | `IVpc`                       | VPC to deploy into | App default VPC |

### Connection Syntax

Connect compute resources to databases, storage, and queues:

```typescript theme={null}
// Simple connection (default access)
const api = app.addCompute(
  ComputeFactory.build("API", {
    type: "ecs",
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        containers: [
          {
            environment: {
              DATABASE_HOST: database.getHostEndpoint(),
            },
          },
        ],
      },
    ],
  }),
);
```

### ECS Parameters

| Parameter  | Type    | Description                        | Default  |
| ---------- | ------- | ---------------------------------- | -------- |
| `services` | `array` | Service configurations (see below) | Required |

#### Service Configuration

Each service in the `services` array:

| Parameter                | Type                                   | Description                       | Default        |
| ------------------------ | -------------------------------------- | --------------------------------- | -------------- |
| `name`                   | `string`                               | Service name                      | Required       |
| `capacityProvider`       | `"FARGATE" \| "FARGATE_SPOT" \| "EC2"` | Compute capacity                  | Required       |
| `cpu`                    | `number`                               | CPU units (256, 512, 1024, etc.)  | `256`          |
| `memoryLimitMiB`         | `number`                               | Memory in MiB                     | `512`          |
| `desiredCount`           | `number`                               | Number of tasks                   | `1`            |
| `containers`             | `array`                                | Container definitions (see below) | Required       |
| `routing`                | `object`                               | ALB routing configuration         | -              |
| `scaling`                | `object`                               | Auto-scaling configuration        | -              |
| `dockerfilePath`         | `string`                               | Path to Dockerfile                | `"Dockerfile"` |
| `dockerTarget`           | `string`                               | Docker build target stage         | -              |
| `ssmSecretsPath`         | `string`                               | SSM Parameter Store path prefix   | -              |
| `taskRoleInlinePolicies` | `object`                               | Custom IAM policies               | -              |

#### Container Configuration

Each container in the `containers` array:

| Parameter       | Type       | Description                       | Default      |
| --------------- | ---------- | --------------------------------- | ------------ |
| `name`          | `string`   | Container name                    | Service name |
| `port`          | `number`   | Container port                    | `80`         |
| `image`         | `string`   | Container image (if not building) | -            |
| `environment`   | `object`   | Environment variables             | `{}`         |
| `secretsImport` | `object`   | Secrets from Secrets Manager      | `{}`         |
| `command`       | `string[]` | Container command                 | -            |
| `healthCheck`   | `object`   | Health check configuration        | -            |

#### Routing Configuration

| Parameter         | Type     | Description           | Default |
| ----------------- | -------- | --------------------- | ------- |
| `path`            | `string` | URL path pattern      | `"/*"`  |
| `host`            | `string` | Host header match     | -       |
| `priority`        | `number` | Rule priority         | Auto    |
| `healthCheckPath` | `string` | Health check endpoint | `"/"`   |

#### Scaling Configuration

| Parameter     | Type          | Description                                                | Default           |
| ------------- | ------------- | ---------------------------------------------------------- | ----------------- |
| `minCapacity` | `number`      | Minimum tasks                                              | `1`               |
| `maxCapacity` | `number`      | Maximum tasks                                              | `1`               |
| `scalingType` | `ScalingType` | Scaling metric (`ScalingType.CPU` or `ScalingType.MEMORY`) | `ScalingType.CPU` |

`scalingType` takes the `ScalingType` enum, not a string. Import it from `@fjall/components-infrastructure`:

```typescript theme={null}
import { ScalingType } from "@fjall/components-infrastructure";

scaling: {
  minCapacity: 2,
  maxCapacity: 10,
  scalingType: ScalingType.CPU,
}
```

### ECS Cluster Configuration

Configure the ECS cluster at the root level of the ComputeFactory:

| Parameter                             | Type                              | Description                             | Default              |
| ------------------------------------- | --------------------------------- | --------------------------------------- | -------------------- |
| `ecrRepository`                       | `IRepository`                     | ECR repository for container images     | App default registry |
| `cluster`                             | `object`                          | Cluster-level configuration             | -                    |
| `cluster.loadBalancer`                | `"public" \| "internal" \| false` | Load balancer type                      | `"public"`           |
| `cluster.directAccess`                | `boolean`                         | Enable direct container access (no ALB) | `false`              |
| `cluster.domain`                      | `string`                          | Custom domain for the cluster ALB       | -                    |
| `cluster.domainConfig`                | `object`                          | Domain configuration options            | -                    |
| `cluster.domainConfig.certificateArn` | `string`                          | ACM certificate ARN                     | -                    |
| `cluster.domainConfig.hostedZoneId`   | `string`                          | Route 53 hosted zone ID                 | -                    |
| `cluster.domainConfig.hostedZoneName` | `string`                          | Route 53 hosted zone name               | -                    |

#### Load Balancer Options

```typescript theme={null}
// Public load balancer (default) - internet-facing
app.addCompute(
  ComputeFactory.build("PublicAPI", {
    type: "ecs",
    cluster: {
      loadBalancer: "public",
    },
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        containers: [{ port: 3000 }],
      },
    ],
  }),
);

// Internal load balancer - VPC only
app.addCompute(
  ComputeFactory.build("InternalAPI", {
    type: "ecs",
    cluster: {
      loadBalancer: "internal",
    },
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        containers: [{ port: 3000 }],
      },
    ],
  }),
);

// No load balancer - direct container access
app.addCompute(
  ComputeFactory.build("Worker", {
    type: "ecs",
    cluster: {
      loadBalancer: false,
      directAccess: true,
    },
    services: [
      {
        name: "worker",
        capacityProvider: "FARGATE",
        containers: [{ port: 3000 }],
      },
    ],
  }),
);
```

#### Custom Domain Configuration

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("WebApp", {
    type: "ecs",
    cluster: {
      loadBalancer: "public",
      domain: "api.example.com",
      domainConfig: {
        certificateArn: "arn:aws:acm:us-east-1:123456789:certificate/abc-123",
        hostedZoneId: "Z1234567890ABC",
        hostedZoneName: "example.com",
      },
    },
    services: [
      {
        name: "web",
        capacityProvider: "FARGATE",
        containers: [{ port: 3000 }],
      },
    ],
  }),
);
```

### EC2 Capacity Provider Configuration

When using `capacityProvider: "EC2"`, additional EC2-specific options are available:

| Parameter                                     | Type                 | Description                          | Default      |
| --------------------------------------------- | -------------------- | ------------------------------------ | ------------ |
| `services[].ec2Config`                        | `object`             | EC2-specific configuration           | -            |
| `services[].ec2Config.instanceType`           | `InstanceType`       | EC2 instance type                    | `t4g.medium` |
| `services[].ec2Config.minCapacity`            | `number`             | Minimum EC2 instances                | `1`          |
| `services[].ec2Config.maxCapacity`            | `number`             | Maximum EC2 instances                | `3`          |
| `services[].ec2Config.spotCapacityPercentage` | `number`             | Percentage of spot instances (0-100) | `0`          |
| `services[].ec2Config.ssh`                    | `SshConfig \| false` | SSH access configuration             | `false`      |

```typescript theme={null}
import { InstanceType } from "aws-cdk-lib/aws-ec2";

app.addCompute(
  ComputeFactory.build("EC2Service", {
    type: "ecs",
    services: [
      {
        name: "app",
        capacityProvider: "EC2",
        cpu: 512,
        memoryLimitMiB: 1024,
        ec2Config: {
          instanceType: new InstanceType("t4g.large"),
          minCapacity: 2,
          maxCapacity: 10,
          spotCapacityPercentage: 50, // 50% spot for cost savings
          ssh: {},
        },
      },
    ],
  }),
);
```

### Multi-Container Service Example

```typescript theme={null}
import { ScalingType } from "@fjall/components-infrastructure";

app.addCompute(
  ComputeFactory.build("WebApp", {
    type: "ecs",
    services: [
      {
        name: "web",
        capacityProvider: "FARGATE",
        cpu: 512,
        memoryLimitMiB: 1024,
        containers: [
          {
            name: "app",
            port: 3000,
            environment: { NODE_ENV: "production" },
          },
          {
            name: "nginx",
            image: "nginx:alpine",
            port: 80,
          },
        ],
        routing: {
          path: "/*",
          healthCheckPath: "/health",
        },
        scaling: {
          minCapacity: 2,
          maxCapacity: 10,
          scalingType: ScalingType.CPU,
        },
      },
    ],
  }),
);
```

### Lambda Parameters

| Parameter              | Type                    | Description                                                       | Default               |
| ---------------------- | ----------------------- | ----------------------------------------------------------------- | --------------------- |
| `deployment`           | `"code" \| "container"` | Deployment type (required)                                        | Required              |
| `handler`              | `string`                | Function handler (code deployment)                                | `"index.handler"`     |
| `architecture`         | `Architecture`          | CPU architecture (`Architecture.ARM_64` or `Architecture.X86_64`) | `Architecture.ARM_64` |
| `timeout`              | `number`                | Timeout in seconds                                                | `3`                   |
| `memorySize`           | `number`                | Memory in MB                                                      | `128`                 |
| `ephemeralStorageSize` | `number`                | Ephemeral storage in MB (512-10240)                               | `512`                 |
| `environment`          | `object`                | Environment variables                                             | `{}`                  |
| `functionUrl`          | `object \| false`       | Function URL configuration                                        | -                     |
| `functionUrl.authType` | `FunctionUrlAuthType`   | Auth type (NONE, AWS\_IAM)                                        | -                     |
| `functionUrl.cors`     | `object`                | CORS configuration                                                | -                     |
| `ssmSecretsPath`       | `string`                | SSM Parameter Store path prefix for secrets                       | -                     |
| `inlinePolicy`         | `PolicyStatement[]`     | Custom IAM policy statements                                      | -                     |
| `description`          | `string`                | Function description                                              | -                     |

`architecture` takes the `Architecture` enum from `aws-cdk-lib/aws-lambda`, not a string. Use `Architecture.ARM_64` or `Architecture.X86_64`.

### EC2 Parameters

| Parameter      | Type                 | Description              | Default             |
| -------------- | -------------------- | ------------------------ | ------------------- |
| `instanceType` | `string`             | EC2 instance type        | `"t4g.micro"`       |
| `ssh`          | `SshConfig \| false` | SSH access configuration | `false`             |
| `userData`     | `UserData`           | Instance startup script  | -                   |
| `machineImage` | `IMachineImage`      | AMI to use               | Latest Amazon Linux |
| `minCapacity`  | `number`             | Min instances in ASG     | `1`                 |
| `maxCapacity`  | `number`             | Max instances in ASG     | `1`                 |

## Database Connections

Connect compute resources to databases:

```typescript theme={null}
const database = app.addDatabase(
  DatabaseFactory.build("MyDatabase", {
    type: "Aurora",
    databaseName: "mydb",
  }),
);

app.addCompute(
  ComputeFactory.build("MyAPI", {
    type: "ecs",
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        containers: [
          {
            environment: {
              DATABASE_HOST: database.getHostEndpoint(),
              DATABASE_NAME: database.getDatabaseName(),
            },
            secretsImport: {
              DATABASE_PASSWORD: database
                .getCredentials()
                .getImport("password"),
            },
          },
        ],
      },
    ],
  }),
);
```

## Lambda Function URLs

Make Lambda functions publicly accessible:

```typescript theme={null}
import { FunctionUrlAuthType } from "aws-cdk-lib/aws-lambda";
import { Duration } from "aws-cdk-lib";

app.addCompute(
  ComputeFactory.build("PublicAPI", {
    type: "lambda",
    deployment: "code",
    handler: "index.handler",
    functionUrl: {
      authType: FunctionUrlAuthType.NONE,
      cors: {
        allowedOrigins: ["*"],
        allowedMethods: ["GET", "POST"],
        allowedHeaders: ["Content-Type"],
        maxAge: Duration.hours(24),
      },
    },
  }),
);
```

## Auto-Scaling

ECS services support auto-scaling:

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("ScalableService", {
    type: "ecs",
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        desiredCount: 2,
        scaling: {
          minCapacity: 2,
          maxCapacity: 10,
        },
      },
    ],
  }),
);
```

## Custom Domains

Configure custom domains for ECS services:

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("WebApp", {
    type: "ecs",
    cluster: {
      domain: "app.example.com",
      domainConfig: {
        certificateArn: "arn:aws:acm:us-east-1:123456789:certificate/abc-123",
      },
    },
    services: [
      {
        name: "web",
        capacityProvider: "FARGATE",
        containers: [{ port: 3000 }],
      },
    ],
  }),
);
```

## Cost Optimisation

### Development Environments

Use Fargate Spot for cost savings:

```typescript theme={null}
// Fargate Spot for dev/test
app.addCompute(
  ComputeFactory.build("DevApp", {
    type: "ecs",
    services: [
      {
        name: "dev",
        capacityProvider: "FARGATE_SPOT",
        cpu: 256,
        memoryLimitMiB: 512,
      },
    ],
  }),
);

// Lambda for batch jobs
app.addCompute(
  ComputeFactory.build("BatchJob", {
    type: "lambda",
    deployment: "code",
    handler: "batch.handler",
    timeout: 900,
    memorySize: 1024,
  }),
);
```

### Production Environments

Right-size resources:

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("ProdAPI", {
    type: "ecs",
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        cpu: 512,
        memoryLimitMiB: 1024,
        desiredCount: 2,
        scaling: {
          minCapacity: 2,
          maxCapacity: 10,
        },
      },
    ],
  }),
);
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Storage Factory" icon="bucket" href="/patterns/storage-factory">
    Create S3 buckets and storage resources.
  </Card>

  <Card title="Database Factory" icon="database" href="/patterns/database-factory">
    Provision Aurora, RDS, DynamoDB, and ClickHouse databases.
  </Card>

  <Card title="Standard Pattern" icon="cubes" href="/patterns/standard-pattern">
    Compose full applications from these factories.
  </Card>

  <Card title="ECS Cluster Resources" icon="server" href="/resources/compute/ecs-cluster">
    Configure ECS clusters for advanced workloads.
  </Card>
</CardGroup>
