Building Reusable Infrastructure with Pulumi Component Resources
Learn how to encapsulate AWS S3 and DynamoDB resources into a Pulumi Component Resource for reuse across stacks, with a concrete TypeScript example and notes on limitations.
10 Dec 2025, 17:41 UTC

Problem: Repeating the same AWS setup
When you need the same S3 bucket and DynamoDB table in multiple stacks, copying and pasting resource definitions leads to drift and maintenance overhead.
What are Component Resources?
A Pulumi Component Resource is a class that extends pulumi.ComponentResource. It groups child resources, exposes inputs and outputs as properties, and can be versioned, tested, and published like any library.
Worked example: S3 bucket + DynamoDB table
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
interface S3DynamoArgs {
bucketName?: string;
tableName?: string;
}
class S3DynamoComponent extends pulumi.ComponentResource {
public readonly bucketName: pulumi.Output;
public readonly tableArn: pulumi.Output;
constructor(name: string, args: S3DynamoArgs, opts?: pulumi.ResourceOptions) {
super("pkg:s3Dynamo:Component", name, args, opts);
const bucket = new aws.s3.Bucket("bucket", { bucket: args.bucketName }, { parent: this });
const table = new aws.dynamodb.Table("table", {
name: args.tableName,
attributes: [{ name: "id", type: "S" }],
hashKey: "id",
billingMode: "PAY_PER_REQUEST",
}, { parent: this });
this.bucketName = bucket.id;
this.tableArn = table.arn;
this.registerOutputs({
bucketName: this.bucketName,
tableArn: this.tableArn,
});
}
}
export { S3DynamoComponent };
Using the component
In another file you can instantiate the component just like any other resource:
import * as pulumi from "@pulumi/pulumi";
import { S3DynamoComponent } from "./s3dynamo";
new S3DynamoComponent("my infra", {
bucketName: "my-unique-bucket",
tableName: "MyTable",
});
Preview and verification
Run pulumi preview (requires AWS credentials and Pulumi CLI installed). You should see two resources listed under the component, e.g. pkg:s3Dynamo:Component with child aws:s3/bucket:Bucket and aws:dynamodb/table:Table. The preview does not modify state; it only shows what would be created.
Trade‑offs
- All child resources share the same stack state file, so a failure in one child can roll back the whole component.
- Deep nesting can hide the underlying AWS resources, making cost attribution and debugging harder.
Packaging for reuse
To share the component, run npm pack in the component’s directory, publish the tarball to a private registry, then add it as a dependency in another Pulumi project and import it as shown above.
Closing
Component Resources give you a language‑native way to encapsulate repeatable infrastructure while keeping the full power of Pulumi’s dependency graph. Start with a small, well‑tested component, verify the preview output, and consider the shared‑state limitation before adding many layers.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.