Skip to main content

Overview

CdnFactory creates AWS CloudFront distributions with type-safe configuration. It delivers global content with caching, HTTPS, and custom domain support.
CDN is configured automatically when using the Payload pattern. Use CdnFactory directly when breaking out of patterns or building custom architectures.
Every configuration requires an originType. Use "auto" to detect the origin from a connected Fjall resource, or set "s3", "alb", or "http" explicitly.

Basic Usage

import { App, CdnFactory } from "@fjall/components-infrastructure";

const app = App.getApp("api");

const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
  }),
);

Configuration

Origin Types

TypeDescriptionUse Case
"auto"Auto-detect from connected resourcesMost common
"s3"S3 bucket originStatic websites
"alb"Application Load Balancer originECS services
"http"Custom HTTP origin (external URL)External backends

Full Configuration Example

const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
    domainNames: ["www.example.com", "example.com"],
    certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
    behaviours: [
      {
        pathPattern: "/_next/static/*",
        origin: assetsBucket,
        cachePolicy: "CACHING_OPTIMIZED",
      },
      {
        pathPattern: "/api/*",
        origin: serverFunction,
        cachePolicy: "CACHING_DISABLED",
      },
      {
        pathPattern: "/media/*",
        origin: assetsBucket,
        cachePolicy: "CACHING_OPTIMIZED",
      },
    ],
  }),
);

Parameters

Core Parameters

ParameterTypeDescriptionDefault
originType"auto" | "s3" | "alb" | "http"Origin type (required)-
originresourceDefault origin resource. Required when originType is "auto"-
domainNamesstring[]Custom domain namesCloudFront domain
certificateArnstringACM certificate ARN as a string (must be in us-east-1)-
certificateICertificateImported ACM certificate construct. Use certificateArn for the string-
The origin field exists only on the "auto" variant. The "s3", "alb", and "http" variants take bucket, loadBalancer, and domainName respectively (see Origin-Specific Parameters).

Behaviour Parameters

Each behaviour accepts these four fields. CloudFront applies viewer protocol policy, origin request policy, and compression automatically.
ParameterTypeDescriptionDefault
behavioursarrayCache behaviour configurationsDefault behaviour
behaviours[].pathPatternstringURL path pattern to match"*"
behaviours[].originresourceOrigin for this pathRequired
behaviours[].cachePolicystringCache policy name"CACHING_OPTIMIZED"
behaviours[].allowedMethods"GET_HEAD" | "GET_HEAD_OPTIONS" | "ALL"HTTP methods for this path"GET_HEAD"

Origin-Specific Parameters

When using explicit origin types, additional parameters are available:

S3 Origin (originType: "s3")

ParameterTypeDescriptionDefault
bucketIBucketS3 bucket to use as originRequired
originPathstringPath prefix in the bucket"/"
CdnFactory.build("StaticCDN", {
  originType: "s3",
  bucket: myBucket,
  originPath: "/public",
});

ALB Origin (originType: "alb")

ParameterTypeDescriptionDefault
loadBalancerIApplicationLoadBalancerALB to use as originRequired
protocolPolicy"HTTP_ONLY" | "HTTPS_ONLY" | "MATCH_VIEWER"Origin protocol policy"HTTPS_ONLY"
CdnFactory.build("ALBCDN", {
  originType: "alb",
  loadBalancer: myAlb,
  protocolPolicy: "HTTPS_ONLY",
});

HTTP Origin (originType: "http")

ParameterTypeDescriptionDefault
domainNamestringExternal domain nameRequired
originPathstringPath prefix at origin"/"
protocolPolicy"HTTP_ONLY" | "HTTPS_ONLY" | "MATCH_VIEWER"Origin protocol policy"HTTPS_ONLY"
CdnFactory.build("ExternalCDN", {
  originType: "http",
  domainName: "api.external-service.com",
  originPath: "/v2",
  protocolPolicy: "HTTPS_ONLY",
});

Additional Configuration

ParameterTypeDescriptionDefault
commentstringDistribution comment/description-
enableLoggingbooleanEnable access loggingfalse
logBucketIBucketS3 bucket for access logs-
priceClass"PriceClass_100" | "PriceClass_200" | "PriceClass_All"Price class (edge locations)"PriceClass_All"
forwardHostHeaderbooleanForward Host header to originfalse
defaultAllowedMethods"GET_HEAD" | "GET_HEAD_OPTIONS" | "ALL"Default allowed HTTP methods"GET_HEAD"

Framework-Managed Behaviour Settings

Fjall sets these per-behaviour values internally. They are not configurable through the factory.
SettingValue
Viewer protocolRedirect HTTP to HTTPS
Origin request policySelected automatically for the origin
CompressionEnabled for compressible content types

Cache Policies

PolicyDescription
"CACHING_OPTIMIZED"Standard caching for static content
"CACHING_OPTIMIZED_FOR_UNCOMPRESSED_OBJECTS"For already-compressed content
"CACHING_DISABLED"No caching (API routes, dynamic content)

Common Patterns

Static Website with S3

const assetsBucket = app.addStorage(
  StorageFactory.build("Assets", {
    websiteHosting: { indexDocument: "index.html" },
  }),
);

const cdn = app.addCdn(
  CdnFactory.build("WebsiteCdn", {
    originType: "s3",
    bucket: assetsBucket,
    domainNames: ["www.example.com"],
    certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
  }),
);

Lambda Function URL (Auto-Detection)

const serverFunction = app.addCompute(
  ComputeFactory.build("Server", {
    type: "lambda",
    deployment: "container",
    functionUrl: { authType: FunctionUrlAuthType.NONE },
  }),
);

const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
  }),
);
With originType: "auto", the factory detects the Lambda function URL from the compute resource.

Multi-Origin Setup (OpenNext)

// Create all resources
const serverFunction = app.addCompute(...);
const imageFunction = app.addCompute(...);
const assetsBucket = app.addStorage(...);

// CDN with multiple origins
const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
    behaviours: [
      {
        pathPattern: "/_next/image*",
        origin: imageFunction,
        cachePolicy: "CACHING_OPTIMIZED",
      },
      {
        pathPattern: "/_next/static/*",
        origin: assetsBucket,
        cachePolicy: "CACHING_OPTIMIZED",
      },
      {
        pathPattern: "/media/*",
        origin: assetsBucket,
        cachePolicy: "CACHING_OPTIMIZED",
      },
    ],
  }),
);

ECS with Load Balancer

The cluster’s load balancer is internet-facing by default. Set routing to match a path on the shared ALB.
const service = app.addCompute(
  ComputeFactory.build("Api", {
    type: "ecs",
    cluster: { loadBalancer: "public" },
    services: [
      {
        name: "api",
        capacityProvider: "FARGATE",
        routing: { path: "/api/*" },
      },
    ],
  }),
);

const cdn = app.addCdn(
  CdnFactory.build("ApiCdn", {
    originType: "alb",
    loadBalancer: service,
    behaviours: [
      {
        pathPattern: "/api/*",
        origin: service,
        cachePolicy: "CACHING_DISABLED",
      },
    ],
  }),
);

Custom Domain Setup

Prerequisites

  1. Domain registered and DNS managed (Route 53 recommended)
  2. ACM certificate in us-east-1 (required for CloudFront)

With Route 53

const cdn = app.addCdn(
  CdnFactory.build("AppCdn", {
    originType: "auto",
    origin: serverFunction,
    domainNames: ["www.example.com"],
    // Route 53 DNS records are created automatically
    certificateArn: "arn:aws:acm:us-east-1:123456789012:certificate/abc-123",
  }),
);

With External DNS

Create a CNAME record pointing to the CloudFront distribution domain:
www.example.com CNAME d1234567890.cloudfront.net

Accessing CDN Information

const cdn = app.addCdn(
  CdnFactory.build("AppCdn", { originType: "auto", origin: serverFunction }),
);

// Read distribution info
const domainName = cdn.getDistributionDomainName();
const distributionId = cdn.getDistributionId();

Security

Automatic Security Features

  • HTTPS only: HTTP automatically redirected to HTTPS
  • TLS 1.2+: Modern TLS protocols only
  • Origin Access Control: Secure S3 bucket access
  • Signed URLs: Optional signed URL support for private content

Best Practices

  1. Use originType: "auto" for most cases. Fjall picks the origin from the connected resource.
  2. Cache static assets with the CACHING_OPTIMIZED policy.
  3. Disable caching for APIs with CACHING_DISABLED to return fresh responses.
  4. Create the certificate in us-east-1. CloudFront requires certificates in this region.

Next Steps

Compute Factory

Deploy Lambda and ECS origins

Storage Factory

Configure S3 bucket origins

Payload Pattern

Full-stack deployment with CDN

Network Factory

Configure VPC networking