Skip to content

Alternatives

1. RSA Key Generation: Lambda vs Pre-Generated

Section titled “1. RSA Key Generation: Lambda vs Pre-Generated”

Chosen: Lambda custom resource (Option A).

Alternative: Pre-generate key pair externally, store in Secrets Manager manually, pass ARN to CDK.

Why rejected: 5 partitions across 3 infrastructures — manual pre-generation doesn’t scale. The existing repo has Lambda custom resource patterns (write-ns-records-to-upstream-dns.ts). Future rotation is a config change, not a manual ceremony.

2. Image Bucket: BulkStoresStack vs ImageStorageStack

Section titled “2. Image Bucket: BulkStoresStack vs ImageStorageStack”

Chosen: Co-located in ImageStorageStack (PD-04).

Original plan: ImageAssetBucket in BulkStoresStack, ImageAssetCdn in a separate stack.

Why changed: CDK’s S3BucketOrigin.withOriginAccessControl() auto-adds a bucket policy referencing the distribution, creating a cross-stack circular dependency. Co-location was also architecturally better — bucket, CDN, and signing keys share the same lifecycle (RETAIN).

3. CDN Stack: Extend PurposeIngress vs New Stack

Section titled “3. CDN Stack: Extend PurposeIngress vs New Stack”

Chosen: New ImageStorageStack (PD-01).

Alternative: Add CDN constructs to the existing PurposeIngress stack.

Why rejected: Different lifecycle (RETAIN vs mutable), different security model (signed cookies vs JWT), different caching (aggressive vs disabled). Separating follows the existing pattern where BulkStoresStack is independent from PurposeIngress.

4. Domain: io.arda.cards vs assets.arda.cards

Section titled “4. Domain: io.arda.cards vs assets.arda.cards”

Chosen: Dedicated assets.arda.cards domain family (PD-02).

Alternative: Use the existing io.arda.cards subdomain zone.

Why rejected: API traffic and static asset delivery serve fundamentally different capabilities — different security models (JWT vs signed cookies), different caching strategies, different content types. Sharing the io domain would conflate these concerns.

5. Presigning Role: Separate Construct vs Embedded

Section titled “5. Presigning Role: Separate Construct vs Embedded”

Chosen: Embedded in ImageAssetBucket (matching UploadBucket pattern).

Alternative: Standalone ImageUploadPresigningRole construct in constructs/iam/.

Why rejected: The presigning role is tightly coupled to the bucket (references bucket ARN, enforces SSE on that bucket). The existing UploadBucket embeds its role. No use case for a standalone role.

6. Root Account Deployment: Full Automation vs Minimal Script

Section titled “6. Root Account Deployment: Full Automation vs Minimal Script”

Chosen: Minimal deploy-root.sh script (PD-03).

Alternative: Full CI automation with GitHub Actions OIDC role for root account.

Why rejected: OIDC role setup for the root account is a separate infrastructure concern. The root zone changes are infrequent (new domain families are rare). A script is sufficient for the current operational model.


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