---
title: Fargate
description: Deploy containerized applications using ECS Fargate and ALB
---
import { Icon } from 'astro-icon/components';
import { Aside } from '@astrojs/starlight/components';
import FargateArchitecture from '@/components/docs/patterns/FargateArchitecture.astro';
import FargatePipeline from '@/components/docs/patterns/FargatePipeline.astro';
Deploy containerized web services on [AWS ECS Fargate](https://aws.amazon.com/fargate/) with an [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/) for scalable, managed container hosting. No EC2 instances, no cluster management — automatic health checks and rolling updates.
## Supported Frameworks
- [Next.js](https://nextjs.org/)
- [Nuxt](https://nuxt.com/)
- [TanStack Start](https://tanstack.com/start/latest)
- [SvelteKit](https://kit.svelte.dev/)
- [Astro](https://astro.build/)
- [NestJS](https://nestjs.com/)
- [Hono](https://hono.dev/)
- Any containerized web application
## AWS Resources
| Resource | Purpose |
| --- | --- |
| [ECS Cluster](https://aws.amazon.com/ecs/) | Container orchestration |
| [Fargate Task](https://aws.amazon.com/fargate/) | Serverless container runtime |
| [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/) | Public HTTP/HTTPS endpoint, health checks |
| [VPC](https://aws.amazon.com/vpc/) | Network isolation (created automatically if not provided) |
| [ECR Repository](https://aws.amazon.com/ecr/) | Container image registry (via CodePipeline) |
| [CloudWatch Logs](https://aws.amazon.com/cloudwatch/) | Container logs, retained for 1 week |
| [ACM Certificate](https://aws.amazon.com/certificate-manager/) | SSL for custom domain (optional) |
| [Route53](https://aws.amazon.com/route53/) | DNS A record (optional) |
## Container Service Architecture
## Quick Start
### Installation
```bash
bun add -D @thunder-so/thunder
```
### Configuration
```ts title="stack/prod.ts"
import { Cdk, Fargate, type FargateProps } from "@thunder-so/thunder";
const config: FargateProps = {
env: {
account: 'YOUR_ACCOUNT_ID',
region: 'us-east-1',
},
application: 'myapp',
service: 'web',
environment: 'prod',
rootDir: '.',
serviceProps: {
dockerFile: 'Dockerfile',
architecture: Cdk.aws_ecs.CpuArchitecture.ARM64,
desiredCount: 1,
cpu: 512,
memorySize: 1024,
port: 3000,
healthCheckPath: '/',
},
};
new Fargate(
new Cdk.App(),
`${config.application}-${config.service}-${config.environment}-stack`,
config
);
```
### Deploy
```bash
npx cdk deploy --app "bunx tsx stack/prod.ts" --profile default
```
CDK builds your Docker image, pushes it to ECR, and deploys the service:
```
Outputs:
myapp-web-prod-stack.LoadBalancerDNS = myapp-web-prod-1234567890.us-east-1.elb.amazonaws.com
```
## Custom Domain
Connect your service to a custom domain. The certificate must be issued in the **same region as your Fargate service**.
```ts title="stack/prod.ts"
const config: FargateProps = {
// ...
domain: 'app.example.com',
hostedZoneId: 'Z1D633PJN98FT9',
regionalCertificateArn: 'arn:aws:acm:us-east-1:123456789012:certificate/abc-123',
};
```
When a domain is configured: HTTPS listener is added on port 443, HTTP on port 80 redirects to HTTPS, and a Route53 A record is created.
## Service Configuration
### Environment Variables and Secrets
```ts title="stack/prod.ts"
const config: FargateProps = {
// ...
serviceProps: {
// ...
variables: [
{ NODE_ENV: 'production' },
{ PUBLIC_API_URL: 'https://api.example.com' },
],
secrets: [
{
key: 'DATABASE_URL',
resource: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:/myapp/DATABASE_URL-abc123',
},
],
},
};
```
Secrets are injected as environment variables at container startup. The task role is automatically granted read access.
### CPU and Memory
Fargate uses fixed CPU/memory combinations. ARM64 (`Cdk.aws_ecs.CpuArchitecture.ARM64`) is cheaper and often faster for Node.js workloads.
| CPU (units) | vCPU | Valid Memory (MB) |
| --- | --- | --- |
| 256 | 0.25 | 512, 1024, 2048 |
| 512 | 0.5 | 1024–4096 |
| 1024 | 1 | 2048–8192 |
| 2048 | 2 | 4096–16384 |
| 4096 | 4 | 8192–30720 |
## Nixpacks Integration
Use [Nixpacks](https://nixpacks.com/) to automatically generate a container image without writing a Dockerfile. When no `dockerFile` is set in `serviceProps`, Thunder runs Nixpacks during `cdk synth` to detect your runtime and generate an optimized build.
Nixpacks auto-detects Node.js, Python, Go, Ruby, Rust, PHP, Java, Deno, and more.
```ts title="stack/prod.ts"
const config: FargateProps = {
// ...
serviceProps: {
// no dockerFile — Nixpacks takes over
port: 3000,
cpu: 512,
memorySize: 1024,
},
buildProps: {
runtime_version: '22', // Node.js version
installcmd: 'bun install',
buildcmd: 'bun run build',
startcmd: 'bun start',
},
};
```
For advanced control, add a `nixpacks.toml` to your project root:
```toml title="nixpacks.toml"
[phases.install]
cmds = ["bun install --frozen-lockfile"]
[phases.build]
cmds = ["bun run build"]
[start]
cmd = "node dist/server.js"
```
## Custom Dockerfile
For full control over the build environment, provide your own Dockerfile. The entire `rootDir` is used as the Docker build context.
```dockerfile title="Dockerfile"
FROM public.ecr.aws/docker/library/node:22-alpine AS builder
WORKDIR /app
COPY package.json bun.lockb ./
RUN curl -fsSL https://bun.sh/install | bash && export PATH="$HOME/.bun/bin:$PATH"
RUN bun install --frozen-lockfile
COPY . .
RUN bun run build
FROM public.ecr.aws/docker/library/node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
EXPOSE 3000
CMD ["node", "dist/server.js"]
```
## Estimated Cost
| Scenario | Monthly (us-east-1, no free tier) |
| --- | --- |
| 1 task (0.25 vCPU / 512 MB) | ~$33 |
| 2 tasks (0.5 vCPU / 1 GB each) | ~$47 |
The ALB (~$22/month) is the dominant fixed cost. See [Fargate pricing](https://aws.amazon.com/fargate/pricing/) and [ALB pricing](https://aws.amazon.com/elasticloadbalancing/pricing/).
## CI/CD Pipeline
### Nixpacks Pipeline
```ts title="stack/prod.ts"
const config: FargateProps = {
// ...
accessTokenSecretArn: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:github-token-XXXXXX',
sourceProps: {
owner: 'your-username',
repo: 'your-repo',
branchOrRef: 'main',
},
buildProps: {
installcmd: 'bun install',
buildcmd: 'bun run build',
startcmd: 'bun start',
},
};
```
### Custom Dockerfile Pipeline
```ts title="stack/prod.ts"
const config: FargateProps = {
// ...
accessTokenSecretArn: 'arn:aws:secretsmanager:us-east-1:123456789012:secret:github-token-XXXXXX',
sourceProps: {
owner: 'your-username',
repo: 'your-repo',
branchOrRef: 'main',
},
serviceProps: {
dockerFile: 'Dockerfile',
port: 3000,
},
};
```
## Stack Outputs
| Output | Description |
| --- | --- |
| `LoadBalancerDNS` | ALB DNS name |
| `Route53Domain` | Custom domain URL (only if `domain` is configured) |
## Destroy
```bash
npx cdk destroy --app "bunx tsx stack/prod.ts" --profile default
```