IaC via SDK Best Practices
Every operation in this section - creating a stack, updating it, checking on it, deploying a CDK app - has a safe way to do it and a shortcut that works until the day it does not.
Busca en todas las páginas de la documentación
Every operation in this section - creating a stack, updating it, checking on it, deploying a CDK app - has a safe way to do it and a shortcut that works until the day it does not.
This page collects the habits worth having before you ship code that deploys or manages infrastructure through the CloudFormation SDK.
UpdateStack directly for anything beyond a disposable stack. It applies immediately with no preview; use CreateChangeSet + DescribeChangeSet + ExecuteChangeSet instead.Replacement field, not just Action. An entry can say Modify and still replace the underlying resource - Replacement is the field that actually tells you.ExecuteChangeSet runs.DeleteChangeSet after a rejected review keeps stacks free of stale, confusing artifacts.Review the diff before anything is applied.
# --- Python (boto3) ---
import boto3
cfn = boto3.client("cloudformation", region_name="us-east-1")
resp = cfn.describe_change_set(StackName="my-stack", ChangeSetName="release-142")
for change in resp["Changes"]:
detail = change["ResourceChange"]
if detail.get("Replacement") == "True":
print("WARNING: replacement", detail["LogicalResourceId"])// --- TypeScript (AWS SDK v3) ---
import { CloudFormationClient, DescribeChangeSetCommand } from "@aws-sdk/client-cloudformation";
const cfn = new CloudFormationClient({ region: "us-east-1" });
const resp = await cfn.send(new DescribeChangeSetCommand({ StackName: "my-stack", ChangeSetName: "release-142" }));
for (const change of resp.Changes ?? []) {
const detail = change.ResourceChange;
if (detail?.Replacement === "True") {
console.log("WARNING: replacement", detail.LogicalResourceId);
}
}EnableTerminationProtection: true on CreateStack (or UpdateTerminationProtection after the fact) blocks accidental DeleteStack calls.DeletionPolicy: Retain or Snapshot on stateful resources. Databases, and anything else you cannot regenerate, should survive a stack deletion even when the rest of the stack is torn down.DeleteStack - handle emptying explicitly rather than discovering this mid-teardown.Replacement: "True" on a stateful resource as a stop-the-line signal. Confirm it is intended before executing the change set.# --- Python (boto3) ---
import boto3
cfn = boto3.client("cloudformation", region_name="us-east-1")
cfn.create_stack(
StackName="my-stack",
TemplateBody=template,
EnableTerminationProtection=True,
)// --- TypeScript (AWS SDK v3) ---
import { CloudFormationClient, CreateStackCommand } from "@aws-sdk/client-cloudformation";
const cfn = new CloudFormationClient({ region: "us-east-1" });
await cfn.send(new CreateStackCommand({
StackName: "my-stack",
TemplateBody: template,
EnableTerminationProtection: true,
}));CreateStack, UpdateStack, DeleteStack, and change-set creation all return before the work finishes - poll with the matching waiter, not a fixed sleep.ClientRequestToken on CreateStack. It makes retries of the same logical request idempotent, so a network retry after a timeout does not attempt to create the stack twice.StackStatus after a waiter succeeds, not just that it returned. A rollback state can still leave the stack in a status you need to react to.DetectStackDrift is a point-in-time check - without a recurring job, drift can go unnoticed for weeks.ListImports before touching an exporting stack. Confirm nothing still depends on an export before attempting to remove or change it.TemplateURL that changed independently is a common source of confusing, hard-to-reproduce updates.Capabilities the template actually needs. Prefer CAPABILITY_IAM over CAPABILITY_NAMED_IAM unless the template genuinely assigns explicit IAM resource names.cloudformation:* and broad downstream service permissions can create anything its templates ask for - review both layers.cdk deploy only when your pipeline needs it. For most teams cdk deploy remains simpler and better supported.ResponseMetadata.RequestId (boto3) or $metadata.requestId (SDK v3) on failure. It is what AWS support needs to look into a failed stack operation.Never apply changes with a bare UpdateStack. Route every update through a change set so replacements are visible before ExecuteChangeSet runs.
Set EnableTerminationProtection: true on the stack, and set DeletionPolicy: Retain or Snapshot on individual stateful resources so they survive even if the stack itself is deleted.
A retry after a timeout, without a ClientRequestToken, can be treated as a new request. Pass a stable token so retries of the same logical call are idempotent.
Treat it as a no-op. Both SDKs raise this when the template or change set introduces no actual differences from the current stack state.
On a recurring schedule - nightly is common - rather than only when you suspect a problem, since it is a point-in-time scan and drift accumulates silently between runs.
Only if nothing imports it. Call ListImports first; CloudFormation blocks the deletion anyway if an import still exists, but checking first avoids a failed deploy step.
No. Bypass it only when your pipeline has its own change-set review or rollback conventions that don't compose with the CDK CLI. Otherwise cdk deploy is simpler and better supported.
It is a broader acknowledgment than the template needs. Request the narrowest capability the template actually requires so a deploy role's scope stays easy to reason about.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Revisado por Chris St. John·Última actualización: 25 jul 2026