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

# Standard Pattern

> Deploy a production-ready Fjall application on AWS with on-demand Fargate, an RDS Instance, and Multi-AZ high availability.

## Overview

Standard is the recommended starting point for production applications. It runs on-demand Fargate tasks across 3 availability zones, backed by an RDS Instance and an Application Load Balancer, with CPU-based auto-scaling and CloudWatch monitoring.

## What's Included

```bash theme={null}
fjall create app --type standard
```

Creates:

* **ECS Fargate** containers (Multi-AZ)
* **RDS Instance** database (Multi-AZ capable)
* **Application Load Balancer**
* **Auto-scaling** configuration
* **CloudWatch** monitoring

## Architecture

```
┌─────────────────┐
│   CloudFront    │ (Optional CDN)
└────────┬────────┘
         |
┌────────┴────────┐
│      ALB        │ (3 AZ)
└────────┬────────┘
         |
┌────────┴────────┐
│  ECS Fargate    │ (2 tasks across AZs)
│  512 CPU        │
│  1024 MiB       │
└────────┬────────┘
         |
┌────────┴────────┐
│  RDS Instance   │ (Multi-AZ option)
└─────────────────┘
```

## Generated Infrastructure

```typescript theme={null}
#!/usr/bin/env node

import {
  App,
  DatabaseFactory,
  ComputeFactory,
  getConfig,
} from "@fjall/components-infrastructure";

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

app.addTags({
  "fjall:costAllocation:owner": "engineering",
});

const myappStorage = app.addDatabase(
  DatabaseFactory.build("MyappStorage", {
    type: "Instance",
    databaseName: "MyappDatabase",
  }),
);

app.addCompute(
  ComputeFactory.build("MyappCompute", {
    type: "ecs",
    ecrRepository: app.getDefaultContainerRegistry(),
    services: [
      {
        name: "app",
        capacityProvider: "FARGATE",
        cpu: 512,
        memoryLimitMiB: 1024,
        desiredCount: 2,
        scaling: {
          maxCapacity: 5,
        },
        containers: [
          {
            port: 3000,
            environment: {
              ENVIRONMENT: getConfig().environment,
              DATABASE_HOST: myappStorage.getHostEndpoint(),
              DATABASE_PORT: `${myappStorage.getHostPort()}`,
              DATABASE_NAME: myappStorage.getDatabaseName(),
            },
            secretsImport: {
              DATABASE_PASSWORD: myappStorage
                .getCredentials()
                .getImport("password"),
            },
          },
        ],
      },
    ],
  }),
);
```

## Specifications

### Compute (ECS Fargate)

* **CPU**: 512 units (0.5 vCPU)
* **Memory**: 1024 MiB
* **Tasks**: 2 (scales up to 5)
* **Auto-scaling**: CPU-based (70% target)
* **Health checks**: Automatic with ALB

### Database (RDS Instance)

* **Engine**: PostgreSQL 17.5
* **Instance**: t4g.large
* **Storage**: 20 GB gp3
* **Backup**: 14-day retention
* **Multi-AZ**: Available (not default)

### Networking

* **VPC**: 3 AZ with public/private subnets
* **Load Balancer**: Application Load Balancer
* **NAT**: 1 NAT gateway
* **Security**: Automatic security groups
* **SSL**: ACM certificate support

## Customisation

### Scaling Configuration

```typescript theme={null}
app.addCompute(
  ComputeFactory.build("MyappCompute", {
    type: "ecs",
    services: [
      {
        name: "app",
        capacityProvider: "FARGATE",
        cpu: 1024, // Increase CPU
        memoryLimitMiB: 2048, // Increase memory
        desiredCount: 2, // Multiple tasks
        scaling: {
          minCapacity: 2, // Minimum for HA
          maxCapacity: 10, // Scale to 10 tasks
        },
      },
    ],
  }),
);
```

### Database Upgrades

```typescript theme={null}
const myappStorage = app.addDatabase(
  DatabaseFactory.build("MyappStorage", {
    type: "Instance",
    databaseName: "MyappDatabase",
    instanceType: "t4g.xlarge", // Larger instance
  }),
);
```

### Enable Multi-AZ Database

After deployment, enable Multi-AZ in AWS Console or via AWS CLI:

```bash theme={null}
aws rds modify-db-instance \
  --db-instance-identifier myapp-database \
  --multi-az \
  --apply-immediately
```

## Cost Estimation

| Resource      | Specification            | Monthly Cost     |
| ------------- | ------------------------ | ---------------- |
| ECS Fargate   | 0.5 vCPU, 1 GB x 2 tasks | \~\$36           |
| RDS Instance  | t4g.large                | \~\$25           |
| Load Balancer | 1 ALB                    | \~\$16           |
| Data Transfer | 100 GB                   | \~\$9            |
| **Total**     |                          | **\~\$86/month** |

*Costs vary by region and usage*

## When to Use

**Perfect for:**

* Production web applications
* APIs with moderate traffic
* Business applications
* SaaS products
* Mobile app backends

**Consider alternatives if:**

* Need high availability and encryption (use Resilient)
* Cost-sensitive with low traffic (use Lightweight)
* Experimenting or learning (use Tinkerer)
* Custom requirements (use Custom)

## Production Checklist

Before going live:

* [ ] Enable Multi-AZ for database
* [ ] Verify desired count is 2+ for HA
* [ ] Configure custom domain
* [ ] Set up monitoring alerts
* [ ] Enable deletion protection
* [ ] Configure backup retention
* [ ] Review security groups
* [ ] Set up CI/CD pipeline

## Monitoring

Standard pattern includes:

### CloudWatch Metrics

* ECS service metrics
* RDS performance metrics
* ALB request metrics
* Custom application metrics

### Alarms (Configure Separately)

```typescript theme={null}
// Example: High CPU alarm
const cpuAlarm = new cloudwatch.Alarm(this, "HighCPU", {
  metric: service.metricCpuUtilization(),
  threshold: 80,
  evaluationPeriods: 2,
});
```

## Security Features

* **Encryption**: At-rest and in-transit
* **Private subnets**: Database isolated
* **Security groups**: Least privilege
* **Secrets Manager**: Database passwords
* **IAM roles**: Service permissions

## Upgrade Paths

### To Resilient Pattern

* Switch database to Aurora
* Increase minimum task count to 4
* Add KMS encryption
* Add enhanced monitoring

### Add Background Workers

```bash theme={null}
fjall add compute --app myapp --name Worker --type ecs
```

## Troubleshooting

### Container Failing to Start

* Check CloudWatch logs
* Verify environment variables
* Confirm the Dockerfile is correct
* Check memory limits

### Database Connection Issues

* Verify security groups
* Check credentials in Secrets Manager
* Confirm the database is running
* Test from bastion host

### High Costs

* Review auto-scaling settings
* Check data transfer
* Optimise container size
* Consider reserved instances

## Breaking Out the Pattern

As your application grows, you may want to customise the infrastructure generated by the Standard pattern. You can decompose it into individual factory calls for full control.

See the individual factory documentation for details:

* [Compute Factory](/patterns/compute-factory) - Customise ECS, Lambda, or EC2 settings
* [Database Factory](/patterns/database-factory) - Configure RDS or Aurora parameters
* [Storage Factory](/patterns/storage-factory) - Manage S3 buckets
* [Network Factory](/patterns/network-factory) - Custom VPC and networking
* [CDN Factory](/patterns/cdn-factory) - CloudFront distribution settings

## Next Steps

<CardGroup cols={2}>
  <Card title="Deploy Application" icon="rocket" href="/deployment/deploy-application">
    Deploy your Standard app to AWS
  </Card>

  <Card title="Add Resources" icon="plus" href="/deployment/add-resources">
    Extend with storage, messaging, or CDN
  </Card>

  <Card title="Compute Factory" icon="microchip" href="/patterns/compute-factory">
    Customise ECS, Lambda, or EC2 settings
  </Card>

  <Card title="Configure CI/CD" icon="code-branch" href="/patterns/buildkite-stack">
    Set up an automated deployment pipeline
  </Card>
</CardGroup>
