Skip to main content

ComputeFactory.build

import { ComputeFactory } from "@fjall/components-infrastructure";
Creates ECS (Fargate/Free Tier/Spot), EC2 Auto Scaling groups, or Lambda functions depending on the type parameter you pass.

Interface

interface IComputeProps {
  // selection
  type?: "ecs" | "ec2" | "lambda";
  ecsType?: "fargate" | "freetier" | "spot";  // Only when type="ecs"
  vpc?: IVpc;
  ecrRepository?: Repository | RepositoryImage;

  // container specific
  parentDomain?: string;
  domainConfig?: DomainConfig;
  containerPort?: number;
  containerEnvironment?: { [key: string]: string };
  containerSecretsImport?: { [key: string]: SecretImport };
  
  // Advanced ECS
  cluster?: {
    domainConfig?: {
      domainName: string;
      hostedZone?: FjallHostedZone;
      region?: string;
    };
  };
  services?: Array<ServiceConfig>;  // Multi-service patterns

  // Lambda specific
  handler?: string;
  code?: Code;
  runtime?: Runtime;
  timeout?: number;
  memorySize?: number;
  lambdaDescription?: string;
  scheduleExpression?: string;  // EventBridge schedule
  environment?: { [key: string]: string };
  inlinePolicy?: PolicyStatement[] | Record<string, PolicyDocument>;
  enableFunctionUrl?: boolean;
  functionUrlAuthType?: FunctionUrlAuthType;
  functionUrlCors?: FunctionUrlCorsOptions;

  // EC2 specific
  instanceType?: string;
  enableSSH?: boolean;
  userData?: UserData;
  machineImage?: IMachineImage;
  minCapacity?: number;
  maxCapacity?: number;

  // connectivity & tags
  connections?: IConnectable[];
  tags?: KeyValue;
}

Key options

PropTypeDefaultNotes
type"ecs" | "ec2" | "lambda""ecs"Compute deployment model
ecsType"fargate" | "freetier" | "spot""fargate"ECS mode (Fargate/Free Tier/Spot)
ecrRepositoryRepository | RepositoryImageFjall defaultContainer image source
containerPortnumber80Exposed port for ECS
containerEnvironmentRecord<string, string>Plain environment variables injected into the running container
containerSecretsImport{ [key: string]: SecretImport }Map secrets from other constructs (for example a database) into container secrets
connectionsIConnectable[]Other constructs this service should reach (all-TCP)
handlerstringLambda handler (required for Lambda)
runtimeRuntimeLambda runtime (required for Lambda)
scheduleExpressionstringEventBridge schedule (e.g., "rate(5 minutes)")
instanceTypestring"t3.micro"EC2 instance type

ECS Container Deployment

Fargate (Serverless)

The default ECS mode - serverless containers:
app.addCompute(
  ComputeFactory.build("BlogApi", {
    type: "ecs",
    ecsType: "fargate",  // serverless
    ecrRepository: ContainerImage.fromRegistry("public.ecr.aws/my/blog:latest"),
    containerPort: 3000,
  })
);
Fargate Configuration: Task count: 2, CPU: 256 units, Memory: 512 MiB, Container Insights V2 enabled

Free Tier

Cost-free development using t3.micro instances:
app.addCompute(
  ComputeFactory.build("DevApi", {
    type: "ecs",
    ecsType: "freetier",
    ecrRepository: app.getDefaultContainerRegistry(),
    containerPort: 8080,
  })
);
Free Tier Configuration: Instance: t3.micro, Min/Max: 1/1, Memory: 400 MiB

Spot Instances

~70% cost savings using Spot capacity:
app.addCompute(
  ComputeFactory.build("BatchProcessor", {
    type: "ecs",
    ecsType: "spot",
    ecrRepository: repo,
    containerPort: 3000,
  })
);
Spot Configuration: Instance: m8g.large (ARM64), Min/Max: 2/3, Desired: 3 tasks

Lambda Functions

Basic Lambda

app.addCompute(
  ComputeFactory.build("DataProcessor", {
    type: "lambda",
    handler: "index.handler",
    code: Code.fromAsset("./build/processor/"),
    runtime: Runtime.NODEJS_20_X,
    timeout: 60,
    memorySize: 512,
    environment: {
      TABLE_NAME: "my-table",
    },
  })
);

Lambda with Scheduled Trigger

app.addCompute(
  ComputeFactory.build("MonitoringWorker", {
    type: "lambda",
    handler: "monitoringWorker.handler",
    code: Code.fromAsset("./build/monitoring/"),
    runtime: Runtime.NODEJS_20_X,
    scheduleExpression: "rate(5 minutes)",
    vpc: undefined,  // No VPC needed for external APIs
    inlinePolicy: [
      new PolicyStatement({
        actions: ["sts:AssumeRole"],
        resources: ["arn:aws:iam::*:role/MonitoringRole-*"],
      }),
    ],
  })
);

Lambda with Function URL

app.addCompute(
  ComputeFactory.build("PublicWebhook", {
    type: "lambda",
    handler: "webhook.handler",
    code: Code.fromAsset("./build/webhook/"),
    runtime: Runtime.NODEJS_20_X,
    enableFunctionUrl: true,
    functionUrlAuthType: FunctionUrlAuthType.NONE,
    functionUrlCors: {
      allowedOrigins: ["https://myapp.com"],
      allowedMethods: [HttpMethod.POST],
    },
  })
);

Example – Fargate service (env + secrets)

// Optional storage resource that provides a secret we’ll import
const db = app.addDatabase(
  DatabaseFactory.build("BlogDb", {
    type: "FreeTier",
    databaseName: "blogdb",
  })
);

app.addCompute(
  ComputeFactory.build("BlogApi", {
    ecrRepository: ContainerImage.fromRegistry(
      "public.ecr.aws/my/blog:latest"
    ),
    containerPort: 3000,

    // Plain environment variables (visible in task definition)
    containerEnvironment: {
      NODE_ENV: "production",
      LOG_LEVEL: "info",
    },

    // Secure secret imported from another construct
    containerSecretsImport: {
      DATABASE_PASSWORD: db.getCredentials().getImport("password"),
    },

    connections: [db], // allow traffic to the database
  })
);
containerSecretsImport maps each key to a SecretImport. The secret is surfaced to the container through AWS Secrets Manager, remaining encrypted at rest and in transit.

Example – Fargate service

app.addCompute(
  ComputeFactory.build("BlogApi", {
    ecrRepository: ContainerImage.fromRegistry(
      "public.ecr.aws/my/blog:latest"
    ),
    containerPort: 3000,
  })
);

Example – EC2 with SSH

app.addCompute(
  ComputeFactory.build("AnalyticsBatch", {
    type: "ec2",
    instanceType: "c6i.large",
    enableSSH: true,
    minCapacity: 2,
    maxCapacity: 10,
  })
);

Best Practices

  • Use App Defaults: app.getDefaultContainerRegistry() and app.getDefaultVpc() for simplified configuration
  • Connection Management: Pass databases to the connections array for automatic security group rules
  • Secret Management: Use containerSecretsImport for sensitive data instead of containerEnvironment
  • Cost Optimization: Use Free Tier for development, Spot for fault-tolerant workloads, disable NAT gateways when possible

See Also