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
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)
app . addCompute (
ComputeFactory . build ( "MyService" , {
type: "ecs" ,
services: [
{
name: "api" ,
capacityProvider: "FARGATE" ,
cpu: 512 ,
memoryLimitMiB: 1024 ,
desiredCount: 2 ,
},
],
}),
);
Fargate Spot (Cost Savings)
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
app . addCompute (
ComputeFactory . build ( "DevService" , {
type: "ecs" ,
services: [
{
name: "dev" ,
capacityProvider: "EC2" ,
cpu: 256 ,
memoryLimitMiB: 512 ,
},
],
}),
);
Lambda Functions
Deploy serverless functions with code deployment:
app . addCompute (
ComputeFactory . build ( "MyFunction" , {
type: "lambda" ,
deployment: "code" , // Required discriminator
handler: "index.handler" ,
memorySize: 512 ,
timeout: 30 ,
}),
);
With container images:
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 ,
}),
);
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.
EC2 Instances
Deploy traditional virtual machines:
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"vpcIVpcVPC to deploy into App default VPC
Connection Syntax
Connect compute resources to databases, storage, and queues:
// 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 servicesarrayService configurations (see below) Required
Service Configuration
Each service in the services array:
Parameter Type Description Default namestringService name Required capacityProvider"FARGATE" | "FARGATE_SPOT" | "EC2"Compute capacity Required cpunumberCPU units (256, 512, 1024, etc.) 256memoryLimitMiBnumberMemory in MiB 512desiredCountnumberNumber of tasks 1containersarrayContainer definitions (see below) Required routingobjectALB routing configuration - scalingobjectAuto-scaling configuration - dockerfilePathstringPath to Dockerfile "Dockerfile"dockerTargetstringDocker build target stage - ssmSecretsPathstringSSM Parameter Store path prefix - taskRoleInlinePoliciesobjectCustom IAM policies -
Container Configuration
Each container in the containers array:
Parameter Type Description Default namestringContainer name Service name portnumberContainer port 80imagestringContainer image (if not building) - environmentobjectEnvironment variables {}secretsImportobjectSecrets from Secrets Manager {}commandstring[]Container command - healthCheckobjectHealth check configuration -
Routing Configuration
Parameter Type Description Default pathstringURL path pattern "/*"hoststringHost header match - prioritynumberRule priority Auto healthCheckPathstringHealth check endpoint "/"
Scaling Configuration
Parameter Type Description Default minCapacitynumberMinimum tasks 1maxCapacitynumberMaximum tasks 1scalingTypeScalingTypeScaling metric (ScalingType.CPU or ScalingType.MEMORY) ScalingType.CPU
scalingType takes the ScalingType enum, not a string. Import it from @fjall/components-infrastructure:
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 ecrRepositoryIRepositoryECR repository for container images App default registry clusterobjectCluster-level configuration - cluster.loadBalancer"public" | "internal" | falseLoad balancer type "public"cluster.directAccessbooleanEnable direct container access (no ALB) falsecluster.domainstringCustom domain for the cluster ALB - cluster.domainConfigobjectDomain configuration options - cluster.domainConfig.certificateArnstringACM certificate ARN - cluster.domainConfig.hostedZoneIdstringRoute 53 hosted zone ID - cluster.domainConfig.hostedZoneNamestringRoute 53 hosted zone name -
Load Balancer Options
// 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
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[].ec2ConfigobjectEC2-specific configuration - services[].ec2Config.instanceTypeInstanceTypeEC2 instance type t4g.mediumservices[].ec2Config.minCapacitynumberMinimum EC2 instances 1services[].ec2Config.maxCapacitynumberMaximum EC2 instances 3services[].ec2Config.spotCapacityPercentagenumberPercentage of spot instances (0-100) 0services[].ec2Config.sshSshConfig | falseSSH access configuration false
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
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 handlerstringFunction handler (code deployment) "index.handler"architectureArchitectureCPU architecture (Architecture.ARM_64 or Architecture.X86_64) Architecture.ARM_64timeoutnumberTimeout in seconds 3memorySizenumberMemory in MB 128ephemeralStorageSizenumberEphemeral storage in MB (512-10240) 512environmentobjectEnvironment variables {}functionUrlobject | falseFunction URL configuration - functionUrl.authTypeFunctionUrlAuthTypeAuth type (NONE, AWS_IAM) - functionUrl.corsobjectCORS configuration - ssmSecretsPathstringSSM Parameter Store path prefix for secrets - inlinePolicyPolicyStatement[]Custom IAM policy statements - descriptionstringFunction 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 instanceTypestringEC2 instance type "t4g.micro"sshSshConfig | falseSSH access configuration falseuserDataUserDataInstance startup script - machineImageIMachineImageAMI to use Latest Amazon Linux minCapacitynumberMin instances in ASG 1maxCapacitynumberMax instances in ASG 1
Database Connections
Connect compute resources to databases:
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:
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:
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:
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:
// 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:
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
Storage Factory Create S3 buckets and storage resources.
Database Factory Provision Aurora, RDS, DynamoDB, and ClickHouse databases.
Standard Pattern Compose full applications from these factories.
ECS Cluster Resources Configure ECS clusters for advanced workloads.