Skip to content

Logical-ID Permanence

Open in ChatGPTOpen in Claude

The second argument to every new Construct(this, "ThisId", …) call becomes part of a CloudFormation logical ID. Once a stack is deployed, that logical ID is permanent: if a later template uses a different ID for “the same” resource, CloudFormation doesn’t rename anything — it deletes the old resource and creates a new one. For stateful resources (DynamoDB tables, Cognito user pools, S3 buckets), that is data loss in production, triggered by what looks like a harmless refactor.

// ✓ Use the registered ID — even if you'd name it differently today
new apigateway.CognitoUserPoolsAuthorizer(this, "CognitoAuthorizer", { ... });
// ✗ NEVER rename — this is a delete-and-recreate, not a rename
new apigateway.CognitoUserPoolsAuthorizer(this, "CognitoAuth", { ... });

An ID that “seems wrong” stays. Cosmetic consistency is never worth destroying a deployed resource.

  • CONSTRUCT_IDS.md — every construct ID the framework creates is registered in a single file, and each construct family exports its IDs as frozen constants (for example API_STACK_IDS, WORKER_STACK_IDS) rather than string literals scattered through the code.
  • CI gatecheck-construct-ids.js fails any change that introduces an unregistered ID or touches a registered one. Snapshot tests over the examples catch the blast radius from the other direction: an ID change shows up as a resource replacement in the template diff.
  • Breaking-change policy — renaming any registered construct ID is a MAJOR version bump with a migration guide, in the same category as removing a public type.
  • Treat your own construct IDs with the same respect once a stage is deployed. Your scaffolded tests/synth.test.ts snapshots give you the same early warning the framework’s examples give it.
  • CDK builds the final logical ID from the construct path, strips non-alphanumeric characters, and appends a hash — so two things follow: moving a construct to a different parent is also a replacement, and you should never assert exact logical-ID strings in tests (assert on a registered prefix instead).
  • Migrating an existing resource into Axis? Lambda configs accept a constructId override precisely so an imported resource can keep the logical ID it already has in production.

Logical-ID permanence is the reason several other Axis decisions look conservative: stacks are never renamed even as they grow responsibilities, new capability always arrives as additive resources, and IDs live in frozen exported constants. The discipline is invisible when it works — which is the point.

© 2026 Axis Tech. Powered by axis-tech.co.