Skip to content

Composite Resources

A composite groups related resources into a single reusable unit. Instead of defining multiple related resources separately every time, you define them once as a composite and instantiate it with props.

Use Composite<Props> from @intentius/chant. The factory function receives props and returns a record of named resources:

src/composite-definition.ts
import { Sub, Role, Function } from "@intentius/chant-lexicon-aws";
import { Composite } from "@intentius/chant";
interface LambdaServiceProps {
name: string | ReturnType<typeof Sub>;
handler: string;
runtime?: string;
timeout?: number;
}
export const LambdaService = Composite<LambdaServiceProps>((props) => {
const role = new Role({
AssumeRolePolicyDocument: {
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Principal: { Service: "lambda.amazonaws.com" },
Action: "sts:AssumeRole",
}],
},
});
const func = new Function({
FunctionName: props.name,
Handler: props.handler,
Runtime: props.runtime ?? "nodejs20.x",
Role: role.Arn,
Timeout: props.timeout ?? 30,
Code: { ZipFile: "exports.handler = async () => ({});" },
});
return { role, func };
}, "LambdaService");

This defines a LambdaService composite that creates two resources: a role and a function.

Instantiate a composite by calling it with props:

src/composite-usage.ts
import { Sub, AWS } from "@intentius/chant-lexicon-aws";
import { LambdaService } from "./composite-definition";
export const api = LambdaService({
name: Sub`${AWS.StackName}-api`,
handler: "index.handler",
});

This produces all underlying resources with names derived from the props. The composite instance exposes its members directly, so api.role and api.func are accessible for cross-references.

Within the factory, you can reference other members directly since they’re just variables in the same scope (as seen in the definition above — role: role.arn).

Outside the composite, access members via the instance:

export const monitor = new _.Alarm({
alarmName: "api-errors",
dimensions: [{ name: "FunctionName", value: api.func.functionName }],
});

Composites are useful when:

  • Multiple resources always appear together — a function always needs a role and log destination
  • You want consistent naming — derive all resource names from a single name prop
  • Cross-resource wiring is complex — encapsulate the references inside the composite

For sharing default property values across resources of the same type, see Presets instead.

Some lexicons also support child projects — subdirectories that build to separate output files. The parent references a child project via a lexicon-specific function (e.g. AWS nestedStack()), and cross-stack values are explicitly exported with stackOutput(). See Multi-Stack Projects for an overview.

The Kubernetes lexicon ships 27 production-ready composites across four categories. Here’s a quick overview:

Platform-agnostic patterns that work on any conformant cluster:

CompositeWhat it creates
WebAppDeployment + Service + optional Ingress
AutoscaledServiceDeployment + Service + HPA + PDB with probes
CronWorkloadCronJob with RBAC
WorkerPoolQueue worker Deployment with RBAC and autoscaling
NamespaceEnvNamespace with ResourceQuota, LimitRange, and NetworkPolicy
NodeAgentDaemonSet with cluster-wide RBAC and host mounts

Each cloud provider has composites that integrate Kubernetes with its native services:

PatternEKSAKSGKE
Workload identityIrsaServiceAccountAksWorkloadIdentityServiceAccountWorkloadIdentityServiceAccount
IngressAlbIngressAgicIngressGceIngress / GkeGateway
Block storageEbsStorageClassAzureDiskStorageClassGcePdStorageClass
Shared storageEfsStorageClassAzureFileStorageClassFilestoreStorageClass
DNSExternalDnsAgentAksExternalDnsAgentGkeExternalDnsAgent
ObservabilityFluentBitAgent / AdotCollectorAzureMonitorCollectorGkeFluentBitAgent / GkeOtelCollector

AutoscaledService is the most common composite — a production HTTP service with horizontal autoscaling, disruption budgets, and health probes:

import { AutoscaledService } from "@intentius/chant-lexicon-k8s";
const { deployment, service, hpa, pdb } = AutoscaledService({
name: "api",
image: "api:2.0",
port: 8080,
maxReplicas: 10,
minReplicas: 3,
targetCPUPercent: 60,
targetMemoryPercent: 80,
cpuRequest: "200m",
memoryRequest: "256Mi",
cpuLimit: "1",
memoryLimit: "1Gi",
livenessPath: "/healthz",
readinessPath: "/readyz",
topologySpread: true,
namespace: "production",
});

All four members (deployment, service, hpa, pdb) are available for cross-references just like any other resource.

  • Generic Composites — WebApp, AutoscaledService, CronWorkload, WorkerPool, NamespaceEnv, NodeAgent
  • EKS Composites — IRSA, ALB Ingress, EBS/EFS storage, CloudWatch, ADOT, ExternalDNS
  • AKS Composites — Workload Identity, AGIC Ingress, Azure Disk/Files, Azure Monitor, ExternalDNS
  • GKE Composites — Workload Identity, GCE Ingress, Gateway API, PD/Filestore, Cloud Logging, Config Connector