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

# ECS Cluster

> Deploy multi-service container workloads on AWS ECS with Fjall, sharing one load balancer across Fargate and EC2 services.

## Overview

The ECS Cluster resource deploys containerised applications on AWS ECS with a multi-service architecture. A single cluster hosts one or more services that share a load balancer. Each service specifies its own capacity provider ("FARGATE", "FARGATE\_SPOT", or "EC2"), containers, CPU/memory, and scaling rules.

## Resource Class

```typescript theme={null}
import EcsCluster, {
  Protocol,
  ScalingType,
} from "@fjall/components-infrastructure/lib/resources/aws/compute/ecs";
```

`EcsCluster` is the default export from the module.

## Basic Usage

### Single Service

```typescript theme={null}
const cluster = new EcsCluster(this, "WebCluster", {
  clusterName: "WebCluster",
  ecrRepository: ecr,
  services: [
    {
      name: "web",
      capacityProvider: "FARGATE",
      containers: [{ name: "app", port: 3000 }],
    },
  ],
});
```

### Multi-Service with Routing

```typescript theme={null}
const cluster = new EcsCluster(this, "ApiCluster", {
  clusterName: "ApiCluster",
  ecrRepository: ecr,
  cluster: { domain: "api.example.com" },
  services: [
    {
      name: "users",
      capacityProvider: "FARGATE",
      containers: [{ name: "app", port: 3000 }],
      routing: { path: "/users/*" },
    },
    {
      name: "orders",
      capacityProvider: "FARGATE",
      containers: [{ name: "app", port: 3001 }],
      routing: { path: "/orders/*" },
    },
  ],
});
```

### Worker Cluster (No Load Balancer)

```typescript theme={null}
const cluster = new EcsCluster(this, "Workers", {
  clusterName: "Workers",
  ecrRepository: ecr,
  cluster: { loadBalancer: false },
  services: [
    {
      name: "processor",
      capacityProvider: "FARGATE",
      containers: [{ name: "worker" }],
    },
  ],
});
```

## Cluster Props

| Property        | Type                                      | Description                        | Default  |
| --------------- | ----------------------------------------- | ---------------------------------- | -------- |
| `clusterName`   | `string`                                  | Cluster name                       | Required |
| `ecrRepository` | `Repository \| RepositoryImage \| string` | Default container image            | Required |
| `services`      | `EcsServiceProps[]`                       | Services to deploy                 | Required |
| `vpc`           | `IVpc`                                    | VPC for deployment                 | -        |
| `appName`       | `string`                                  | App name for SSM secrets namespace | -        |
| `cluster`       | `EcsClusterClusterConfig`                 | Cluster-level config (domain, ALB) | -        |

### Cluster Configuration

| Property               | Type                              | Description                              | Default    |
| ---------------------- | --------------------------------- | ---------------------------------------- | ---------- |
| `cluster.domain`       | `string`                          | Domain for HTTPS access                  | -          |
| `cluster.loadBalancer` | `false \| "public" \| "internal"` | ALB configuration                        | `"public"` |
| `cluster.directAccess` | `boolean`                         | Direct EC2 access without ALB (EC2 only) | `false`    |
| `cluster.domainConfig` | `DomainConfig`                    | Advanced routing policy                  | -          |

## Service Props

Each service in the `services` array has these properties:

| Property                  | Type                                     | Description                          | Default                              |
| ------------------------- | ---------------------------------------- | ------------------------------------ | ------------------------------------ |
| `name`                    | `string`                                 | Service name (unique within cluster) | Required                             |
| `capacityProvider`        | `"FARGATE" \| "FARGATE_SPOT" \| "EC2"`   | Capacity provider                    | Required                             |
| `containers`              | `EcsClusterContainerConfig[]`            | Container definitions                | Required                             |
| `cpu`                     | `number`                                 | CPU units (256-4096)                 | `256`                                |
| `memoryLimitMiB`          | `number`                                 | Memory in MiB (512-30720)            | `512`                                |
| `desiredCount`            | `number`                                 | Desired number of tasks              | `2`                                  |
| `scalingType`             | `ScalingType`                            | CPU or Memory auto-scaling           | -                                    |
| `minCapacity`             | `number`                                 | Minimum tasks for scaling            | Tracks `desiredCount`                |
| `maxCapacity`             | `number`                                 | Maximum tasks for scaling            | `Math.max(desiredCount + 1, 3)`      |
| `routing`                 | `EcsRoutingConfig \| EcsRoutingConfig[]` | ALB routing rules                    | -                                    |
| `image`                   | `string \| Repository`                   | Service-specific image               | Cluster default                      |
| `connections`             | `ConnectionSpec[]`                       | Resources to connect to              | -                                    |
| `taskRoleInlinePolicies`  | `{ [name: string]: PolicyDocument }`     | Additional task role policies        | -                                    |
| `taskRoleManagedPolicies` | `IManagedPolicy[]`                       | Managed policies for task role       | -                                    |
| `ec2Config`               | `Ec2CapacityConfig`                      | EC2 capacity settings (EC2 only)     | -                                    |
| `ssmSecretsPath`          | `string`                                 | SSM secrets base path                | `/<appName>/<clusterName>/<service>` |
| `dockerTarget`            | `string`                                 | Docker build target stage            | -                                    |

### Routing Configuration

| Property          | Type     | Description                             | Default       |
| ----------------- | -------- | --------------------------------------- | ------------- |
| `path`            | `string` | Path pattern (e.g., "/api/\*")          | -             |
| `host`            | `string` | Host header (e.g., "api.example.com")   | -             |
| `priority`        | `number` | Rule priority (1-50000, lower = higher) | Auto-assigned |
| `healthCheckPath` | `string` | Target group health check path          | `"/"`         |

## Container Configuration

Each container in the `containers` array has these properties:

| Property        | Type                              | Description                       | Default             |
| --------------- | --------------------------------- | --------------------------------- | ------------------- |
| `name`          | `string`                          | Container name                    | Required            |
| `port`          | `number`                          | Port the container listens on     | -                   |
| `image`         | `string \| Repository`            | Container image                   | Cluster default ECR |
| `environment`   | `Record<string, string>`          | Environment variables             | -                   |
| `secrets`       | `string[]`                        | SSM Parameter Store secret names  | -                   |
| `secretsImport` | `{ [key: string]: SecretImport }` | Secrets Manager imports           | -                   |
| `command`       | `string[]`                        | Container command                 | -                   |
| `entryPoint`    | `string[]`                        | Container entry point             | -                   |
| `essential`     | `boolean`                         | Stop task if this container stops | `true`              |
| `healthCheck`   | `object`                          | Health check configuration        | Auto for primary    |

The first container with a `port` is the **primary container** and receives load balancer traffic. All other containers act as sidecars.

## Capacity Providers

### FARGATE

Serverless containers. No infrastructure to manage.

```typescript theme={null}
{
  name: "api",
  capacityProvider: "FARGATE",
  cpu: 512,
  memoryLimitMiB: 1024,
  containers: [{ name: "app", port: 3000 }]
}
```

### FARGATE\_SPOT

Up to 70% cheaper than standard Fargate. Tasks may be interrupted.

```typescript theme={null}
{
  name: "batch",
  capacityProvider: "FARGATE_SPOT",
  cpu: 1024,
  memoryLimitMiB: 2048,
  containers: [{ name: "worker" }]
}
```

### EC2

Run containers on EC2 instances you control.

```typescript theme={null}
{
  name: "gpu-worker",
  capacityProvider: "EC2",
  ec2Config: {
    instanceType: "t4g.micro",   // Default: "t4g.micro"
    minCapacity: 1,
    maxCapacity: 3,
    desiredCapacity: 2,
    memoryLimitMiB: 1024
  },
  containers: [{ name: "worker" }]
}
```

## Auto-Scaling

### CPU-Based Scaling

```typescript theme={null}
{
  name: "api",
  capacityProvider: "FARGATE",
  containers: [{ name: "app", port: 3000 }],
  scalingType: ScalingType.CPU,
  minCapacity: 2,
  maxCapacity: 20
}
```

### Memory-Based Scaling

```typescript theme={null}
{
  name: "cache",
  capacityProvider: "FARGATE",
  containers: [{ name: "app", port: 8080 }],
  scalingType: ScalingType.MEMORY,
  minCapacity: 1,
  maxCapacity: 10
}
```

## Secrets and Environment Variables

### Environment Variables

```typescript theme={null}
{
  name: "api",
  capacityProvider: "FARGATE",
  containers: [{
    name: "app",
    port: 3000,
    environment: {
      NODE_ENV: "production",
      LOG_LEVEL: "info"
    }
  }]
}
```

### SSM Parameter Store Secrets

```typescript theme={null}
{
  name: "api",
  capacityProvider: "FARGATE",
  ssmSecretsPath: "/myapp/api-cluster/api",
  containers: [{
    name: "app",
    port: 3000,
    secrets: ["API_KEY", "DB_PASSWORD"]
  }]
}
```

### Secrets Manager Imports

```typescript theme={null}
{
  name: "api",
  capacityProvider: "FARGATE",
  containers: [{
    name: "app",
    port: 3000,
    secretsImport: {
      DB_PASSWORD: { name: "prod/database", field: "password" }
    }
  }]
}
```

## Multi-Container Tasks

The first container with a `port` is the primary container. Additional containers run as sidecars.

```typescript theme={null}
{
  name: "api",
  capacityProvider: "FARGATE",
  cpu: 512,
  memoryLimitMiB: 1024,
  containers: [
    {
      name: "app",
      port: 3000,
      environment: { NODE_ENV: "production" }
    },
    {
      name: "datadog",
      image: "datadog/agent:latest",
      environment: { DD_API_KEY: "..." }
    }
  ]
}
```

## Connections

Services can declare resources they need to connect to. The construct creates security group rules for network resources and IAM grants for storage resources.

```typescript theme={null}
{
  name: "api",
  capacityProvider: "FARGATE",
  containers: [{ name: "app", port: 3000 }],
  connections: [
    database,                              // Security group (RDS)
    { resource: cache, access: "read" },   // Read-only DynamoDB
    { resource: bucket, access: "write" }, // Write-only S3
    { resource: queue, access: "consume" } // Consume-only SQS
  ]
}
```

## Methods

### Get Load Balancer

```typescript theme={null}
const alb = cluster.getLoadBalancer();
// Returns: ApplicationLoadBalancer | undefined
```

### Get Service

```typescript theme={null}
const service = cluster.getService("api");
// Returns: FargateService | Ec2Service | undefined
```

### Get All Services

```typescript theme={null}
const services = cluster.getServices();
// Returns: Map<string, FargateService | Ec2Service>
```

### Get Cluster

```typescript theme={null}
const cdkCluster = cluster.getCluster();
// Returns: Cluster (CDK ECS Cluster)
```

### Get URL

```typescript theme={null}
const url = cluster.getUrl();
// Returns: "https://api.example.com" or "http://..." or undefined
```

## Complete Example

```typescript theme={null}
import EcsCluster, {
  ScalingType,
} from "@fjall/components-infrastructure/lib/resources/aws/compute/ecs";
import { Repository } from "aws-cdk-lib/aws-ecr";

const repo = new Repository(this, "AppRepo");

const cluster = new EcsCluster(this, "ProductionCluster", {
  clusterName: "prod-cluster",
  ecrRepository: repo,
  vpc: vpc,
  appName: "myapp",
  cluster: {
    domain: "api.example.com",
    loadBalancer: "public",
  },
  services: [
    {
      name: "api",
      capacityProvider: "FARGATE",
      cpu: 1024,
      memoryLimitMiB: 2048,
      scalingType: ScalingType.CPU,
      minCapacity: 2,
      maxCapacity: 10,
      containers: [
        {
          name: "app",
          port: 8080,
          environment: {
            NODE_ENV: "production",
            PORT: "8080",
          },
          secrets: ["API_KEY"],
        },
      ],
      routing: { path: "/api/*", healthCheckPath: "/health" },
      connections: [database],
    },
    {
      name: "worker",
      capacityProvider: "FARGATE_SPOT",
      cpu: 512,
      memoryLimitMiB: 1024,
      containers: [{ name: "worker" }],
      connections: [queue, database],
    },
  ],
});
```

## Best Practices

1. **Use FARGATE** for production workloads requiring isolation
2. **Use FARGATE\_SPOT** for batch processing and fault-tolerant workloads
3. **Set appropriate CPU/memory** based on application needs
4. **Enable auto-scaling** for production with min 2 tasks
5. **Use secrets** for sensitive data, not environment variables
6. **Configure routing** when deploying multiple services with ports
7. **Use connections** for declarative resource access

## Next Steps

<CardGroup cols={2}>
  <Card title="Compute Factory" icon="layer-group" href="/patterns/compute-factory">
    Provision an ECS cluster through the higher-level compute factory pattern.
  </Card>

  <Card title="Application Load Balancer" icon="scale-balanced" href="/resources/networking/load-balancer">
    Configure the ALB that fronts your cluster services.
  </Card>

  <Card title="ECR Repository" icon="box" href="/resources/storage/ecr-repository">
    Store the container images your services pull at deploy time.
  </Card>

  <Card title="Security Group" icon="shield" href="/resources/networking/security-group">
    Control network access to and from your ECS services.
  </Card>
</CardGroup>
