Skip to content

Learnings

1. CDK Provider Framework Handler Contract

Section titled “1. CDK Provider Framework Handler Contract”

Lesson: CDK’s custom_resources.Provider wraps the Lambda handler. The handler must return { PhysicalResourceId, Data } — the framework sends the CloudFormation response. If the handler sends the response directly via HTTPS (raw CloudFormation pattern), the Provider sends its own empty response, losing all Data attributes.

Impact: Three failed deployments before identifying the root cause. The error message (Vendor response doesn't contain PublicKeyPem attribute) was misleading — the Lambda logs showed the data was generated correctly.

Recommendation: Document the Provider handler contract in the knowledge base. All future inline Lambdas must follow the return pattern.

2. Cross-Stack OAC Creates Circular Dependencies

Section titled “2. Cross-Stack OAC Creates Circular Dependencies”

Lesson: S3BucketOrigin.withOriginAccessControl() auto-adds a bucket policy referencing the CloudFront distribution ARN. When bucket and distribution are in different stacks, this creates a cyclic CloudFormation reference.

Impact: Required architectural change during implementation — ImageAssetBucket moved from BulkStoresStack to ImageStorageStack (PD-04). This was actually a better design: bucket, CDN, and signing keys form a cohesive unit with shared lifecycle.

Recommendation: Always co-locate S3 buckets with their CloudFront distributions when using OAC.

Lesson: r53.ARecord’s recordName is appended to the zone name. Passing the full FQDN causes double-qualification.

Impact: Failed deployment with RRSet not permitted in zone.

Recommendation: Use only the subdomain prefix (e.g., locator.id) as recordName, never the full FQDN.

4. Ingress Stack Exports Parent Domain, Not Zone Domain

Section titled “4. Ingress Stack Exports Parent Domain, Not Zone Domain”

Lesson: InfrastructureIngress exports domainName as the parent domain (assets.arda.cards) rather than the actual zone name (alpha002.assets.arda.cards). This is consistent with io/app/auth but breaks zone-relative DNS record creation.

Impact: Failed deployment — Route53 tried to create a record in the wrong zone.

Recommendation: When adding new domain families that use zone-relative naming, export the zone’s actual domain name from the Route53HostedZone.built.domainName property.

5. RETAIN Resources Require Manual Cleanup

Section titled “5. RETAIN Resources Require Manual Cleanup”

Lesson: Resources with RemovalPolicy.RETAIN survive stack rollback. Each failed deployment creates orphans (S3 bucket, Secrets Manager secret, CloudFront PublicKey, CloudFront KeyGroup) that block subsequent deployments.

Impact: Required manual cleanup between each retry — deleting key group, public key, secret, bucket, then the stack itself, in the correct order.

Recommendation: Document the cleanup procedure (done in knowledge base). Consider adding a cleanup script for development environments.

6. Planning Documents Need Deployment Validation

Section titled “6. Planning Documents Need Deployment Validation”

Lesson: The specification described the correct architecture, but several implementation details only surfaced during actual deployment: Lambda handler pattern, DNS naming, export values.

Impact: 3 code fixes discovered during deployment (not caught by cdk synth or unit tests). CDK synth validates CloudFormation structure but not runtime behavior of custom resources or DNS resolution.

Recommendation: Include a deployment to a dev environment as an explicit task in Run 2 (which we did — task 2.18). The verification script was essential for catching the remaining issues.

7. Test Infrastructure Should Be Established Early

Section titled “7. Test Infrastructure Should Be Established Early”

Lesson: Setting up Jest, path aliases, and understanding CDK assertion limitations took significant time. Several test patterns didn’t work (Match.anyValue() in arrayWith(), hasOutput("*"), snapshot hash instability).

Impact: Multiple test fix iterations during CI.

Recommendation: Establish test infrastructure and patterns in a dedicated task before writing construct code. Document CDK assertion gotchas in the knowledge base (done).


Copyright: (c) Arda Systems 2025-2026, All rights reserved