Components
Components are reusable, parameterized infrastructure modules. They encapsulate resources, inputs, and outputs into a single unit.
Component Type Declaration
component WebServer { // Inputs - configurable parameters input string hostname input number port = 8080 // Internal resources resource EC2.Instance server { name = hostname } // Outputs - exposed values output string endpoint = "${hostname}:${port}"}Component Instantiation
// Define the component typecomponent WebServer { input string hostname input number port = 8080}// Create instancescomponent WebServer main { hostname = "localhost" port = 3000}component WebServer api { hostname = "api.example.com" port = main.port // Reference another instance}Inputs
Inputs are configurable parameters for components:
component Database { input string name // Required input (no default) input number port = 5432 // Optional input (with default) input string[] allowedIps = [] // Typed array input input boolean sslEnabled = true // Boolean input}Input Decorators
component Server { @description("The server hostname") @nonEmpty input string hostname @minValue(1) @maxValue(65535) input number port = 8080 @sensitive input string apiKey}Outputs
Outputs expose values from components:
component WebServer { input string hostname input number port = 8080 resource EC2.Instance server { name = hostname } output string endpoint = "${hostname}:${port}" // Simple output output string serverId = server.id // Output from resource output string url = "https://${hostname}:${port}" // Computed output}Accessing Component Properties
Define a component, then instantiate it:
component WebServer { input string hostname input number port = 8080 output string endpoint = "http://${hostname}:${port}" resource VM.Instance server { name = hostname }}Create an instance and access its properties:
component WebServer main { hostname = "localhost" port = 3000}var host = main.hostname // "localhost"var p = main.port // 3000var url = main.endpoint // "http://localhost:3000"// Resources are private (not accessible from outside)// main.server // ERROR: resources are privateWhy Resources Are Private
Resources are private to enforce clean component APIs, enable safe refactoring, and follow the principle of "expose behavior, not implementation."
Prevents Tight Coupling
Without this restriction, consumers could write:
// BAD: Tight coupling to internal structurevar ip = webServer.server.privateIpvar disk = webServer.server.rootVolume.sizeThis creates fragile dependencies on internal implementation. Components force authors to explicitly define what's public:
| Element | Visibility | Purpose |
|---|---|---|
input | Public | Configuration parameters |
output | Public | Computed/exposed values |
resource | Private | Infrastructure implementation |
Enables Safe Refactoring
The component author can change internal resources without breaking consumers:
// v1: Uses VMcomponent WebServer { resource VM.Instance server { ... } output string endpoint = server.publicIp}// v2: Switched to container - consumers unaffectedcomponent WebServer { resource ECS.Service service { ... } output string endpoint = service.loadBalancerUrl}If main.server was allowed, refactoring would break all callers.
Encapsulation (Information Hiding)
Components expose a public contract (inputs/outputs) while hiding implementation details (resources). This is the same principle as private fields in OOP.
component WebServer { input number port = 8080 output string endpoint = "http://${server.publicIp}:${port}" // Implementation detail - could change without breaking consumers resource VM.Instance server { size = "t2.micro" }}Consumers only care about port (what they provide) and endpoint (what they get back). They shouldn't depend on whether there's a VM, container, or Lambda underneath.
Component Decorators
@count
@count(3)component WebServer replica { hostname = "server-${count}"}// Creates: replica-0, replica-1, replica-2@dependsOn
component Database db { ... }@dependsOn(db)component WebServer api { databaseHost = db.endpoint}@tags
@tags({ Environment: "prod", Team: "platform" })component WebApp main { name = "main-app"}Nested Components
component Frontend { input string name component WebServer server { hostname = "${name}.example.com" } output string url = server.endpoint}component Application { component Frontend web { name = "web" } component Backend api { name = "api" }}Next: Learn about Schemas - structured data types for resources.