Skip to content

Commit fce7888

Browse files
i-am-tommeagancojocarSaraDPH
authored
replaceWith Resource Option (#16594)
* Make it so * Front matter * edits, meta image, date, social copy * Update content/blog/dependent-resource-replacements/index.md * Full switcher * Mention the other SDKs * Change the publish date --------- Co-authored-by: meagancojocar <[email protected]> Co-authored-by: Sara <[email protected]>
1 parent 8db45f6 commit fce7888

File tree

2 files changed

+201
-0
lines changed

2 files changed

+201
-0
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
---
2+
title: "New in Pulumi IaC: `replaceWith` Resource Option"
3+
date: 2025-12-09
4+
meta_desc: "You can now use the `replaceWith` resource option to inform Pulumi of extra dependencies"
5+
meta_image: meta.png
6+
authors:
7+
- tom-harding
8+
tags:
9+
- features
10+
- iac
11+
- releases
12+
13+
social:
14+
twitter: "New in Pulumi IaC: Use the `replaceWith` resource option to declare custom resource dependencies and ensure coordinated replacements across your infrastructure."
15+
linkedin: "Pulumi introduces a powerful new feature for fine-grained infrastructure control: the `replaceWith` resource option. Now you can explicitly define dependencies between resources to ensure coordinated replacements—perfect for scenarios like restarting services when databases are updated or managing complex multi-resource dependencies."
16+
---
17+
18+
The magic of Pulumi is that we rarely have to worry about the fine details of *how* our deployment and infrastructure management works, allowing us to focus instead on *what* we want. If our program declares an S3 bucket, Pulumi handles creation, updates, and deletion automatically.
19+
20+
Most of the time, this is exactly what we want. However, some use cases require finer-grained control over resource dependencies. Today, we're introducing the `replaceWith` resource option, a new feature that gives you explicit control over replacement dependencies between resources.
21+
22+
<!--more-->
23+
24+
## Custom resource dependencies
25+
26+
When replacing a resource, the Pulumi engine walks the dependency graph to determine what else needs replacement. However, the answer isn't always obvious:
27+
28+
* Some dependencies aren't obvious at the infrastructure level. For example, restarting a database server may require restarting its consumers to reconnect.
29+
30+
* Provider-specific challenges exist. You might not be able to update a subnet's properties while resources are using it, even without an observable dependency. Any subnet change must be accompanied by changes to all its consumers to avoid errors.
31+
32+
* Application-level dependencies may exist beyond infrastructure. If two services maintain open connections in the application layer, replacing one should trigger replacement of the other.
33+
34+
## Declaring our own dependencies
35+
36+
The `replaceWith` resource option makes these dependencies explicit in your code. Similar to `deletedWith`, passing references to other resources via `replaceWith` defines a relationship: when any target resource is replaced, the source is also replaced. This has some interesting implications:
37+
38+
* We can define a number of resources that all `replaceWith` each other, and so any change to any member of the group will trigger an update to all the others.
39+
40+
* Relationships are transitive: organizing resources hierarchically where children `replaceWith` their parents means any ancestor change triggers replacement of all descendants.
41+
42+
## In code
43+
44+
{{< chooser language "typescript,python,go,csharp,java,yaml" >}}
45+
46+
{{% choosable language typescript %}}
47+
48+
```typescript
49+
import * as pulumi from "@pulumi/pulumi";
50+
import * as aws from "@pulumi/aws";
51+
52+
const database = new aws.rds.Instance("app-db", { /* ... */ });
53+
54+
// The database location is provided to this instance
55+
// by other means, so there is not an explicit dependency
56+
// linking the two.
57+
const app = new aws.ec2.Instance("app-service", { /* ... */ }, {
58+
// Here, we explicitly tie the two together: if the
59+
// database is upgraded, for example, we will need to
60+
// restart the application instance to ensure that
61+
// a connection is re-established.
62+
replaceWith: [database],
63+
});
64+
```
65+
66+
{{% /choosable %}}
67+
{{% choosable language python %}}
68+
69+
```python
70+
import pulumi
71+
import pulumi_aws as aws
72+
73+
database = aws.rds.Instance('app-db', {})
74+
75+
# The database location is provided to this instance
76+
# by other means, so there is not an explicit dependency
77+
# linking the two.
78+
application = aws.ec2.Instance('app-service', {},
79+
# Here, we explicitly tie the two together: if the
80+
# database is upgraded, for example, we will need to
81+
# restart the application instance to ensure that
82+
# a connection is re-established.
83+
opts=pulumi.ResourceOptions(replace_with=[database])
84+
)
85+
```
86+
87+
{{% /choosable %}}
88+
{{% choosable language go %}}
89+
90+
```go
91+
import (
92+
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/ec2"
93+
"github.com/pulumi/pulumi-aws/sdk/v6/go/aws/rds"
94+
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
95+
)
96+
97+
database, err := rds.NewInstance(ctx, "app-db", &rds.InstanceArgs{ ... })
98+
if err != nil {
99+
return err
100+
}
101+
102+
// The database location is provided to this instance
103+
// by other means, so there is not an explicit dependency
104+
// linking the two.
105+
application, err := ec2.NewInstance(ctx, "app-service", &ec2.InstanceArgs{ ... },
106+
// Here, we explicitly tie the two together; if the
107+
// database is upgraded, for example, we will need to
108+
// restart the application instance to ensure that
109+
// a connection is re-established.
110+
pulumi.ReplaceWith([]pulumi.Resource{database}))
111+
if err != nil {
112+
return err
113+
}
114+
```
115+
116+
{{% /choosable %}}
117+
{{% choosable language csharp %}}
118+
119+
```csharp
120+
using Pulumi;
121+
using Aws = Pulumi.Aws;
122+
123+
var database = new Aws.Rds.Instance("app-db", new() { ... });
124+
125+
// The database location is provided to this instance
126+
// by other means, so there is not an explicit dependency
127+
// linking the two.
128+
var application = new Aws.Ec2.Instance("app-service", new() { ... }, new CustomResourceOptions
129+
{
130+
// Here, we explicitly tie the two together; if the
131+
// database is upgraded, for example, we will need to
132+
// restart the application instance to ensure that
133+
// a connection is re-established.
134+
ReplaceWith = new[]
135+
{
136+
database,
137+
},
138+
});
139+
```
140+
141+
{{% /choosable %}}
142+
{{% choosable language java %}}
143+
144+
```java
145+
import com.pulumi.aws.ec2.Instance;
146+
import com.pulumi.aws.ec2.InstanceArgs;
147+
import com.pulumi.resources.CustomResourceOptions;
148+
149+
var database = new com.pulumi.aws.rds.Instance("app-db",
150+
com.pulumi.aws.rds.InstanceArgs.builder()
151+
.build());
152+
153+
// The database location is provided to this instance
154+
// by other means, so there is not an explicit dependency
155+
// linking the two.
156+
var application = new Instance("app-service",
157+
InstanceArgs.builder()
158+
.build(),
159+
// Here, we explicitly tie the two together; if the
160+
// database is upgraded, for example, we will need to
161+
// restart the application instance to ensure that
162+
// a connection is re-established.
163+
CustomResourceOptions.builder()
164+
.replaceWith(database)
165+
.build());
166+
```
167+
168+
{{% /choosable %}}
169+
{{% choosable language yaml %}}
170+
171+
```yaml
172+
resources:
173+
database:
174+
type: aws:rds:Instance
175+
properties:
176+
# ...
177+
# The database location is provided to this instance
178+
# by other means, so there is not an explicit dependency
179+
# linking the two.
180+
application:
181+
type: aws:ec2:Instance
182+
properties:
183+
# ...
184+
options:
185+
# Here, we explicitly tie the two together: if the
186+
# database is upgraded, for example, we will need to
187+
# restart the application instance to ensure that
188+
# a connection is re-established.
189+
replaceWith:
190+
- ${database}
191+
```
192+
193+
{{% /choosable %}}
194+
195+
{{< /chooser >}}
196+
197+
Of course, this is a simple example, but hopefully it illustrates the point: we now have a way to make implicit dependencies between resources more explicit within our programs, and provide hints to Pulumi as to which services depend on others.
198+
199+
## Next steps
200+
201+
This feature is supported as of [Pulumi `v3.207.0`](https://github.com/pulumi/pulumi/releases/tag/v3.207.0), and is now available within the Go, Python, NodeJS, and Java SDKs, with C# and YAML coming soon. Thanks for reading, and feel free to reach out with any questions via [GitHub](https://github.com/pulumi/pulumi), [X](https://x.com/pulumicorp), or our [Community Slack](https://slack.pulumi.com/).
637 KB
Loading

0 commit comments

Comments
 (0)