Logical-ID Permanence
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.
The rule
Section titled “The rule”// ✓ Use the registered ID — even if you'd name it differently todaynew apigateway.CognitoUserPoolsAuthorizer(this, "CognitoAuthorizer", { ... });
// ✗ NEVER rename — this is a delete-and-recreate, not a renamenew apigateway.CognitoUserPoolsAuthorizer(this, "CognitoAuth", { ... });An ID that “seems wrong” stays. Cosmetic consistency is never worth destroying a deployed resource.
How Axis enforces it
Section titled “How Axis enforces it”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 exampleAPI_STACK_IDS,WORKER_STACK_IDS) rather than string literals scattered through the code.- CI gate —
check-construct-ids.jsfails 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.
What this means in your project
Section titled “What this means in your project”- Treat your own construct IDs with the same respect once a stage is deployed. Your scaffolded
tests/synth.test.tssnapshots 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
constructIdoverride precisely so an imported resource can keep the logical ID it already has in production.
Why the framework is strict about this
Section titled “Why the framework is strict about this”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.