Skip to content

AWS.CloudFront reference

Source: packages/aws/src/CloudFront/CachePolicy.ts

A CloudFront cache policy.

Cache policies determine the values CloudFront includes in the cache key, the headers, cookies and query strings it forwards to the origin, and the TTL bounds for cached responses. Policies are referenced by ID on a Distribution’s default behavior or per-path cache behaviors.

For AWS-managed policies (CachingOptimized, CachingDisabled, AllViewerExceptHostHeader) reference them by ID via the constants in ManagedPolicies instead of creating a custom policy.

const cachePolicy = yield* CachePolicy("ApiCachePolicy", {
comment: "Cache GETs by query string + Authorization",
minTTL: 0,
defaultTTL: "1 minute",
maxTTL: "1 hour",
parametersInCacheKeyAndForwardedToOrigin: {
EnableAcceptEncodingGzip: true,
EnableAcceptEncodingBrotli: true,
HeadersConfig: {
HeaderBehavior: "whitelist",
Headers: { Quantity: 1, Items: ["Authorization"] },
},
CookiesConfig: { CookieBehavior: "none" },
QueryStringsConfig: { QueryStringBehavior: "all" },
},
});

CachePolicy: Looking up an existing cache policy

Section titled “CachePolicy: Looking up an existing cache policy”

CachePolicy.lookup references a cache policy Alchemy doesn’t manage (created in the console or by another stack), found by cachePolicyId or name, AWS managed policies included. It is read during plan/deploy and never created, updated or deleted.

const policy = AWS.CloudFront.CachePolicy.lookup({ name: "Managed-CachingOptimized" });
const cachePolicyId = policy.cachePolicyId;

Source: packages/aws/src/CloudFront/CreateInvalidation.ts

Grants a Function permission to create CloudFront cache invalidations for a distribution at runtime — the classic post-publish/CMS purge pattern.

CreateInvalidation: Invalidating from a Function

Section titled “CreateInvalidation: Invalidating from a Function”
const invalidate = yield* CloudFront.CreateInvalidation(distribution);
const response = yield* invalidate({
InvalidationBatch: {
CallerReference: crypto.randomUUID(),
Paths: { Quantity: 1, Items: ["/blog/*"] },
},
});
// response.Invalidation?.Id

Source: packages/aws/src/CloudFront/DeleteKey.ts

Runtime binding for cloudfront-keyvaluestore:DeleteKey.

Deletes a single key from the bound KeyValueStore’s data plane. Writes use optimistic concurrency: pass the store’s current ETag as IfMatch (from DescribeKeyValueStore or a previous write’s response). Provide the implementation with Effect.provide(AWS.CloudFront.DeleteKeyHttp).

// init — bind the operations to the store
const describeStore = yield* CloudFront.DescribeKeyValueStore(store);
const deleteKey = yield* CloudFront.DeleteKey(store);
// runtime
const meta = yield* describeStore({});
yield* deleteKey({ Key: "routes:/about", IfMatch: meta.ETag });

Source: packages/aws/src/CloudFront/DescribeKeyValueStore.ts

Runtime binding for cloudfront-keyvaluestore:DescribeKeyValueStore.

Reads the bound KeyValueStore’s data-plane metadata — item count, total size, and the current ETag that write operations (PutKey, DeleteKey, UpdateKeys) require as IfMatch. Provide the implementation with Effect.provide(AWS.CloudFront.DescribeKeyValueStoreHttp).

DescribeKeyValueStore: Reading KeyValueStore Data

Section titled “DescribeKeyValueStore: Reading KeyValueStore Data”
// init — bind the operation to the store
const describeStore = yield* CloudFront.DescribeKeyValueStore(store);
// runtime
const meta = yield* describeStore({});
console.log(meta.ETag, meta.ItemCount);

Source: packages/aws/src/CloudFront/Distribution.ts

A CloudFront distribution.

Distribution manages the CDN layer for static sites and HTTP origins such as Lambda Function URLs and ALBs. It exposes the distribution domain and hosted zone ID needed for Route 53 alias records.

CDN in Front of an HTTP Origin

import * as AWS from "@alchemy.run/aws";
const distribution = yield* AWS.CloudFront.Distribution("ApiCdn", {
origins: [
{
id: "api",
domainName: "abc123.lambda-url.us-west-2.on.aws",
customOriginConfig: { originProtocolPolicy: "https-only" },
},
],
defaultCacheBehavior: {
targetOriginId: "api",
viewerProtocolPolicy: "redirect-to-https",
cachePolicyId: AWS.CloudFront.MANAGED_CACHING_DISABLED_POLICY_ID,
originRequestPolicyId:
AWS.CloudFront.MANAGED_ALL_VIEWER_EXCEPT_HOST_HEADER_POLICY_ID,
},
});

Private S3 Origin

const distribution = yield* Distribution("WebsiteCdn", {
aliases: ["www.example.com"],
origins: [
{
id: "site",
domainName: bucket.bucketRegionalDomainName,
s3Origin: true,
originAccessControlId: oac.originAccessControlId,
},
],
defaultCacheBehavior: {
targetOriginId: "site",
viewerProtocolPolicy: "redirect-to-https",
compress: true,
},
viewerCertificate: {
acmCertificateArn: certificate.certificateArn,
sslSupportMethod: "sni-only",
minimumProtocolVersion: "TLSv1.2_2021",
},
});

Set webFunction on an origin to serve an AWS.Lambda.WebFunction (or a WebFunctionEndpoint) through CloudFront. Alchemy creates the origin access control that signs each origin request and grants only this distribution permission to invoke the endpoint. The endpoint must use authType: "IamAuth", so requests that skip CloudFront are refused.

CloudFront in front of a Web Function

const api = yield* AWS.Lambda.WebFunction("Api", {
main: "./src/server.ts",
authType: "IamAuth",
});
const cdn = yield* AWS.CloudFront.Distribution("Cdn", {
origins: [{ id: "api", webFunction: api }],
defaultCacheBehavior: { targetOriginId: "api" },
});

Behaviors that target the origin don’t cache, forward the whole viewer request except Host, and allow every method. Override any of that on the behavior, e.g. cache static assets under a path:

Cache one path, pass everything else through

const cdn = yield* AWS.CloudFront.Distribution("Cdn", {
origins: [{ id: "api", webFunction: api }],
defaultCacheBehavior: { targetOriginId: "api" },
orderedCacheBehaviors: [
{
pathPattern: "/assets/*",
targetOriginId: "api",
cachePolicyId: AWS.CloudFront.MANAGED_CACHING_OPTIMIZED_POLICY_ID,
},
],
});
// declaratively, whenever `version` changes:
yield* AWS.CloudFront.Invalidation("PurgeBlog", {
distributionId: distribution.distributionId,
paths: ["/blog/*"],
version: buildId,
});

To purge at runtime from a Lambda Function, bind CloudFront.CreateInvalidation(distribution) instead.

Distribution: Looking up an existing distribution

Section titled “Distribution: Looking up an existing distribution”

Distribution.lookup references a distribution Alchemy doesn’t manage (created in the console or by another stack), found by distributionId. It is read during plan/deploy and never created, updated or deleted.

const cdn = AWS.CloudFront.Distribution.lookup({ distributionId: "E2ABCDEF123456" });
const domainName = cdn.domainName;

Source: packages/aws/src/CloudFront/Function.ts

A CloudFront Function for viewer request and response customization.

CloudFront Functions are lightweight JavaScript handlers that run at the edge and can be attached to distribution cache behaviors.

const fn = yield* Function("RouterRequestFunction", {
code: `
async function handler(event) {
event.request.headers["x-forwarded-host"] = {
value: event.request.headers.host.value,
};
return event.request;
}
`,
});

Function: Looking up an existing CloudFront function

Section titled “Function: Looking up an existing CloudFront function”

Function.lookup references a CloudFront function Alchemy doesn’t manage (created in the console or by another stack), found by functionName. It is read during plan/deploy and never created, updated or deleted.

const rewrite = AWS.CloudFront.Function.lookup({ functionName: "rewrite-index" });
const functionArn = rewrite.functionArn;

Source: packages/aws/src/CloudFront/GetInvalidation.ts

Runtime binding for cloudfront:GetInvalidation.

Reads the status of a cache invalidation on the bound distribution — pairs with CreateInvalidation to poll a purge to Completed. Provide the implementation with Effect.provide(AWS.CloudFront.GetInvalidationHttp).

// init — bind the operation to the distribution
const getInvalidation = yield* CloudFront.GetInvalidation(distribution);
// runtime
const res = yield* getInvalidation({ Id: invalidationId });
console.log(res.Invalidation?.Status); // "InProgress" | "Completed"

Source: packages/aws/src/CloudFront/GetKey.ts

Runtime binding for cloudfront-keyvaluestore:GetKey.

Reads a single key’s value from the bound KeyValueStore’s data plane. Values are sensitive — distilled decodes them as Redacted<string>; unwrap with Redacted.value. Provide the implementation with Effect.provide(AWS.CloudFront.GetKeyHttp).

// init — bind the operation to the store
const getKey = yield* CloudFront.GetKey(store);
// runtime
const res = yield* getKey({ Key: "routes:/about" });
const value = typeof res.Value === "string" ? res.Value : Redacted.value(res.Value);

Source: packages/aws/src/CloudFront/Invalidation.ts

A CloudFront cache invalidation request.

Invalidation is a helper resource for website deployments that need to clear selected CloudFront cache paths after asset updates.

const invalidation = yield* Invalidation("WebsiteInvalidation", {
distributionId: distribution.distributionId,
version: files.version,
});

Source: packages/aws/src/CloudFront/KeyGroup.ts

A CloudFront key group.

Key groups bundle one or more PublicKey resources for use as TrustedKeyGroups on a Distribution’s cache behavior. CloudFront uses the keys in the group to verify the signatures on signed URLs and signed cookies for that behavior.

const primary = yield* PublicKey("PrimarySigningKey", {
encodedKey: yield* fs.readFileString("./primary.pem"),
});
const secondary = yield* PublicKey("SecondarySigningKey", {
encodedKey: yield* fs.readFileString("./secondary.pem"),
});
const keyGroup = yield* KeyGroup("SignedUrlKeys", {
comment: "Trusted signers for /private",
items: [primary.publicKeyId, secondary.publicKeyId],
});

KeyGroup: Looking up an existing key group

Section titled “KeyGroup: Looking up an existing key group”

KeyGroup.lookup references a key group Alchemy doesn’t manage (created in the console or by another stack), found by keyGroupId or name. It is read during plan/deploy and never created, updated or deleted.

const signers = AWS.CloudFront.KeyGroup.lookup({ name: "signers" });
const keyGroupId = signers.keyGroupId;

Source: packages/aws/src/CloudFront/KeyValueStore.ts

A CloudFront KeyValueStore for edge metadata.

KeyValueStores can be associated with CloudFront Functions and are useful for routing metadata or other small edge-time lookup tables.

const store = yield* KeyValueStore("RouterStore", {
comment: "Route metadata",
});

KeyValueStore: Looking up an existing key value store

Section titled “KeyValueStore: Looking up an existing key value store”

KeyValueStore.lookup references a key value store Alchemy doesn’t manage (created in the console or by another stack), found by keyValueStoreName. It is read during plan/deploy and never created, updated or deleted.

const flags = AWS.CloudFront.KeyValueStore.lookup({ keyValueStoreName: "flags" });

Source: packages/aws/src/CloudFront/KvEntries.ts

Manages namespaced key-value entries in a CloudFront KeyValueStore.

Entries are stored with a {namespace}:{key} prefix to allow multiple logical groups within a single store. Updates use batched optimistic concurrency with automatic ETag retry.

Basic Entries

const entries = yield* KvEntries("Routes", {
store: store.keyValueStoreArn,
namespace: "routes",
entries: {
"/": "/index.html",
"/about": "/about.html",
},
});

Purge Stale Keys

const entries = yield* KvEntries("Routes", {
store: store.keyValueStoreArn,
namespace: "routes",
entries: { "/": "/index.html" },
purge: true,
});

Source: packages/aws/src/CloudFront/KvRoutesUpdate.ts

Manages a single route entry in a JSON array stored in a CloudFront KeyValueStore.

The routes array is stored at key {namespace}:{key} and supports automatic chunking when the serialized array exceeds 1000 characters.

const update = yield* KvRoutesUpdate("MyRoute", {
store: store.keyValueStoreArn,
namespace: "app",
key: "routes",
entry: "site,mysite,*,/",
});

Source: packages/aws/src/CloudFront/ListInvalidations.ts

Runtime binding for cloudfront:ListInvalidations.

Lists the cache invalidations of the bound distribution (paginated via Marker/MaxItems). Provide the implementation with Effect.provide(AWS.CloudFront.ListInvalidationsHttp).

ListInvalidations: Inspecting Invalidations

Section titled “ListInvalidations: Inspecting Invalidations”
// init — bind the operation to the distribution
const listInvalidations = yield* CloudFront.ListInvalidations(distribution);
// runtime
const res = yield* listInvalidations({ MaxItems: 10 });
console.log(res.InvalidationList?.Items?.map((i) => i.Id));

Source: packages/aws/src/CloudFront/ListKeys.ts

Runtime binding for cloudfront-keyvaluestore:ListKeys.

Lists key/value pairs in the bound KeyValueStore’s data plane (paginated via NextToken/MaxResults). Provide the implementation with Effect.provide(AWS.CloudFront.ListKeysHttp).

// init — bind the operation to the store
const listKeys = yield* CloudFront.ListKeys(store);
// runtime
const res = yield* listKeys({ MaxResults: 50 });
console.log(res.Items?.map((item) => item.Key));

Source: packages/aws/src/CloudFront/OriginAccessControl.ts

A CloudFront Origin Access Control for private origins.

OriginAccessControl is the recommended CloudFront access model for private S3 origins and newer signed-origin integrations.

OriginAccessControl: Creating Origin Access Controls

Section titled “OriginAccessControl: Creating Origin Access Controls”
const oac = yield* OriginAccessControl("SiteOriginAccess", {
originType: "s3",
});

OriginAccessControl: Looking up an existing origin access control

Section titled “OriginAccessControl: Looking up an existing origin access control”

OriginAccessControl.lookup references an origin access control Alchemy doesn’t manage (created in the console or by another stack), found by originAccessControlId or name. It is read during plan/deploy and never created, updated or deleted.

const oac = AWS.CloudFront.OriginAccessControl.lookup({ name: "s3-sigv4" });
const originAccessControlId = oac.originAccessControlId;

Source: packages/aws/src/CloudFront/OriginRequestPolicy.ts

A CloudFront origin request policy.

Origin request policies control which values from the viewer request (in addition to those used in the cache key) CloudFront includes when sending a request to the origin. They are referenced by ID on a Distribution’s default behavior or per-path cache behaviors.

OriginRequestPolicy: Creating Origin Request Policies

Section titled “OriginRequestPolicy: Creating Origin Request Policies”
const originRequestPolicy = yield* OriginRequestPolicy("AppOriginRequest", {
comment: "Forward auth + locale",
headersConfig: {
HeaderBehavior: "whitelist",
Headers: { Quantity: 2, Items: ["Authorization", "Accept-Language"] },
},
cookiesConfig: { CookieBehavior: "all" },
queryStringsConfig: { QueryStringBehavior: "all" },
});

OriginRequestPolicy: Looking up an existing origin request policy

Section titled “OriginRequestPolicy: Looking up an existing origin request policy”

OriginRequestPolicy.lookup references an origin request policy Alchemy doesn’t manage (created in the console or by another stack), found by originRequestPolicyId or name, AWS managed policies included. It is read during plan/deploy and never created, updated or deleted.

const policy = AWS.CloudFront.OriginRequestPolicy.lookup({ name: "Managed-AllViewer" });
const originRequestPolicyId = policy.originRequestPolicyId;

Source: packages/aws/src/CloudFront/PublicKey.ts

A CloudFront public key.

Public keys are uploaded ahead of being grouped into a KeyGroup and used by Distributions for signed URL or signed cookie verification.

The key body is immutable after creation — changing encodedKey triggers a replacement (CloudFront returns no API to rotate a key in place).

const key = yield* PublicKey("SignedUrlKey", {
encodedKey: Redacted.make(yield* fs.readFileString("./public_key.pem")),
comment: "RSA-2048 signed URL key for /private",
});

PublicKey: Looking up an existing public key

Section titled “PublicKey: Looking up an existing public key”

PublicKey.lookup references a public key Alchemy doesn’t manage (created in the console or by another stack), found by publicKeyId or name. It is read during plan/deploy and never created, updated or deleted.

const signers = AWS.CloudFront.PublicKey.lookup({ name: "signers" });
const publicKeyId = signers.publicKeyId;

Source: packages/aws/src/CloudFront/PutKey.ts

Runtime binding for cloudfront-keyvaluestore:PutKey.

Creates or replaces a single key in the bound KeyValueStore’s data plane. Writes use optimistic concurrency: pass the store’s current ETag as IfMatch (from DescribeKeyValueStore or a previous write’s response). Provide the implementation with Effect.provide(AWS.CloudFront.PutKeyHttp).

// init — bind the operations to the store
const describeStore = yield* CloudFront.DescribeKeyValueStore(store);
const putKey = yield* CloudFront.PutKey(store);
// runtime
const meta = yield* describeStore({});
const res = yield* putKey({
Key: "routes:/about",
Value: "/about.html",
IfMatch: meta.ETag,
});
// res.ETag is the store's new entity tag

Source: packages/aws/src/CloudFront/RealtimeLogConfig.ts

A CloudFront real-time log configuration.

Real-time logs deliver per-request records to a Kinesis data stream within seconds. Attach the configuration to a distribution’s cache behavior via Distribution (realtimeLogConfigArn).

RealtimeLogConfig: Creating Real-Time Log Configs

Section titled “RealtimeLogConfig: Creating Real-Time Log Configs”
const stream = yield* Kinesis.Stream("EdgeLogs", {});
const role = yield* IAM.Role("EdgeLogsRole", {
assumeRolePolicyDocument: {
Version: "2012-10-17",
Statement: [
{
Effect: "Allow",
Principal: { Service: "cloudfront.amazonaws.com" },
Action: "sts:AssumeRole",
},
],
},
inlinePolicies: {
kinesis: {
Version: "2012-10-17",
Statement: [
{
Effect: "Allow",
Action: [
"kinesis:DescribeStreamSummary",
"kinesis:DescribeStream",
"kinesis:PutRecord",
"kinesis:PutRecords",
],
Resource: stream.streamArn,
},
],
},
},
});
const logConfig = yield* RealtimeLogConfig("EdgeLogConfig", {
samplingRate: 100,
fields: ["timestamp", "c-ip", "cs-uri-stem", "sc-status"],
endpoints: [{ streamArn: stream.streamArn, roleArn: role.roleArn }],
});

RealtimeLogConfig: Looking up an existing realtime log config

Section titled “RealtimeLogConfig: Looking up an existing realtime log config”

RealtimeLogConfig.lookup references a realtime log config Alchemy doesn’t manage (created in the console or by another stack), found by name. It is read during plan/deploy and never created, updated or deleted.

const existing = AWS.CloudFront.RealtimeLogConfig.lookup({ name: "my-realtime-log-config" });

Source: packages/aws/src/CloudFront/ResponseHeadersPolicy.ts

A CloudFront response headers policy.

Response headers policies add or remove headers in viewer responses, including CORS, standard security headers (HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, etc.), Server-Timing, custom headers and explicit header removal. They are referenced by ID on a Distribution’s default behavior or per-path cache behaviors.

ResponseHeadersPolicy: Creating Response Headers Policies

Section titled “ResponseHeadersPolicy: Creating Response Headers Policies”
const responseHeadersPolicy = yield* ResponseHeadersPolicy("AppResponseHeaders", {
comment: "Default app security + CORS",
corsConfig: {
AccessControlAllowOrigins: { Quantity: 1, Items: ["https://app.example.com"] },
AccessControlAllowMethods: { Quantity: 2, Items: ["GET", "OPTIONS"] },
AccessControlAllowHeaders: { Quantity: 1, Items: ["Authorization"] },
AccessControlAllowCredentials: false,
OriginOverride: true,
},
securityHeadersConfig: {
StrictTransportSecurity: {
AccessControlMaxAgeSec: 31536000,
IncludeSubdomains: true,
Preload: true,
Override: true,
},
ContentTypeOptions: { Override: true },
FrameOptions: { FrameOption: "DENY", Override: true },
ReferrerPolicy: { ReferrerPolicy: "no-referrer", Override: true },
},
});

ResponseHeadersPolicy: Looking up an existing response headers policy

Section titled “ResponseHeadersPolicy: Looking up an existing response headers policy”

ResponseHeadersPolicy.lookup references a response headers policy Alchemy doesn’t manage (created in the console or by another stack), found by responseHeadersPolicyId or name, AWS managed policies included. It is read during plan/deploy and never created, updated or deleted.

const policy = AWS.CloudFront.ResponseHeadersPolicy.lookup({ name: "Managed-SecurityHeadersPolicy" });
const responseHeadersPolicyId = policy.responseHeadersPolicyId;

Source: packages/aws/src/CloudFront/UpdateKeys.ts

Runtime binding for cloudfront-keyvaluestore:UpdateKeys.

Puts and/or deletes multiple keys in the bound KeyValueStore’s data plane as a single all-or-nothing batch. Writes use optimistic concurrency: pass the store’s current ETag as IfMatch (from DescribeKeyValueStore or a previous write’s response). Provide the implementation with Effect.provide(AWS.CloudFront.UpdateKeysHttp).

// init — bind the operations to the store
const describeStore = yield* CloudFront.DescribeKeyValueStore(store);
const updateKeys = yield* CloudFront.UpdateKeys(store);
// runtime
const meta = yield* describeStore({});
yield* updateKeys({
IfMatch: meta.ETag,
Puts: [{ Key: "routes:/", Value: "/index.html" }],
Deletes: [{ Key: "routes:/legacy" }],
});

Source: packages/aws/src/CloudFront/VpcOrigin.ts

A CloudFront VPC origin.

VpcOrigin lets a CloudFront distribution route to a private Application Load Balancer, Network Load Balancer, or EC2 instance inside a VPC without exposing it to the public internet. Reference the resulting vpcOriginId from a distribution origin’s vpcOriginConfig.

Private ALB Origin

const vpcOrigin = yield* VpcOrigin("AppOrigin", {
arn: loadBalancer.arn,
httpPort: 80,
httpsPort: 443,
originProtocolPolicy: "https-only",
});

Attaching a VPC Origin to a Distribution

const distribution = yield* Distribution("AppCdn", {
origins: [
{
id: "app",
domainName: loadBalancer.dnsName,
vpcOriginConfig: { vpcOriginId: vpcOrigin.vpcOriginId },
},
],
defaultCacheBehavior: {
targetOriginId: "app",
viewerProtocolPolicy: "redirect-to-https",
},
});

VpcOrigin: Looking up an existing VPC origin

Section titled “VpcOrigin: Looking up an existing VPC origin”

VpcOrigin.lookup references a VPC origin Alchemy doesn’t manage (created in the console or by another stack), found by vpcOriginId. It is read during plan/deploy and never created, updated or deleted.

const existing = AWS.CloudFront.VpcOrigin.lookup({ vpcOriginId: "..." });