Resource Basics
Why Resources & Providers Matter
The Problem: Cloud infrastructure spans hundreds of services across multiple providers, each with different APIs and configuration options.
The Solution: Pulumi resources provide a unified programming model where every cloud service is a typed object with inputs, outputs, and lifecycle management.
Real Impact: With 100+ providers and thousands of resource types, you can manage your entire cloud estate from a single codebase.
Real-World Analogy
Think of resources and providers like a hardware store:
- Provider = A specific brand/manufacturer (DeWalt, Bosch, Makita)
- Resource = A specific tool from that brand (drill, saw, sander)
- Resource Args = The specifications you choose (voltage, speed, size)
- Resource Options = How you want the tool handled (warranty, delivery, protection)
- Outputs = What you get back (serial number, actual specs, receipt)
The Resource Model
Custom Resources
Map directly to a single cloud resource like an S3 bucket, EC2 instance, or Azure SQL database.
Component Resources
Logical groupings of multiple resources that form a higher-level abstraction like a VPC with subnets.
Provider Resources
Configure how Pulumi communicates with a cloud provider, including credentials and regions.
Stack Resources
The root resource that represents the entire deployment, automatically created for every stack.
Provider Configuration
Configuring Providers
import * as aws from "@pulumi/aws";
// Default provider (uses stack config for region)
const bucket = new aws.s3.Bucket("default-bucket");
// Explicit provider for a different region
const westProvider = new aws.Provider("west", {
region: "us-west-2",
});
// Use the explicit provider
const westBucket = new aws.s3.Bucket("west-bucket", {}, {
provider: westProvider,
});
// Multi-cloud: Azure provider
import * as azure from "@pulumi/azure-native";
const resourceGroup = new azure.resources.ResourceGroup("rg", {
location: "eastus",
});
Creating Resources
import * as aws from "@pulumi/aws";
// Resource name is the first argument (logical name)
// Resource args is the second argument (configuration)
const vpc = new aws.ec2.Vpc("main-vpc", {
cidrBlock: "10.0.0.0/16",
enableDnsHostnames: true,
enableDnsSupport: true,
tags: { Name: "main-vpc" },
});
// Resources can reference other resources
const subnet = new aws.ec2.Subnet("app-subnet", {
vpcId: vpc.id, // Output from vpc
cidrBlock: "10.0.1.0/24",
availabilityZone: "us-east-1a",
tags: { Name: "app-subnet" },
});
// Export important values
export const vpcId = vpc.id;
export const subnetId = subnet.id;
Resource Options
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// protect: Prevent accidental deletion
const db = new aws.rds.Instance("prod-db", {
engine: "postgres",
instanceClass: "db.r5.large",
allocatedStorage: 100,
}, { protect: true });
// dependsOn: Explicit dependency ordering
const app = new aws.ecs.Service("app", {
/* ... args ... */
}, { dependsOn: [db] });
// ignoreChanges: Ignore specific property changes
const server = new aws.ec2.Instance("server", {
ami: "ami-0abcdef1234567890",
instanceType: "t3.micro",
}, { ignoreChanges: ["ami"] });
// aliases: Rename without recreating
const bucket = new aws.s3.Bucket("new-name", {}, {
aliases: [{ name: "old-name" }],
});
Common Pitfall
Problem: Renaming a resource causes Pulumi to delete and recreate it, potentially causing data loss.
Solution: Use the aliases resource option to tell Pulumi that a resource was renamed. This preserves the existing cloud resource.
Custom vs Component Resources
| Feature | Custom Resource | Component Resource |
|---|---|---|
| Maps to | Single cloud resource | Group of resources |
| Provider | Managed by a provider plugin | Written in your program |
| CRUD | Provider handles create/read/update/delete | Delegates to child resources |
| Example | aws.s3.Bucket, aws.ec2.Instance | VpcWithSubnets, AppCluster |
| Use Case | Individual infrastructure pieces | Reusable infrastructure patterns |
When to Use Component Resources
- Encapsulation: Group related resources (VPC + subnets + route tables)
- Reusability: Create patterns used across multiple stacks or projects
- Abstraction: Hide complexity behind a simple interface
- Organization: Keep the resource tree clean and navigable in the Pulumi console
Quick Reference
Resource Options Reference
| Option | Description | Example |
|---|---|---|
provider |
Explicit provider for the resource | { provider: westProvider } |
dependsOn |
Explicit dependencies | { dependsOn: [vpc, subnet] } |
protect |
Prevent accidental deletion | { protect: true } |
ignoreChanges |
Ignore property drift | { ignoreChanges: ["tags"] } |
aliases |
Previous names for migration | { aliases: [{ name: "old" }] } |
parent |
Parent component resource | { parent: this } |
deleteBeforeReplace |
Delete old before creating new | { deleteBeforeReplace: true } |