Consolidating Multi-Site Infrastructure: CloudFront Routing, S3 Bucket Deduplication, and DNS CNAME Shadowing in the dangerouscentaur.com Ecosystem

What Was Done

During this session, we completed infrastructure cleanup and validation for adamcherrycomics.dangerouscentaur.com, a Stripe-integrated booking site operating within a shared multi-tenant CloudFront distribution. The work involved:

  • Verified and deleted the stale per-site S3 bucket (s3://adamcherrycomics.dangerouscentaur.com/)
  • Confirmed CloudFront origin architecture correctly routes through a shared bucket with intelligent rewrites
  • Documented DNS architecture to clarify why the per-site bucket was safe to remove
  • Validated that all live traffic is served by the consolidated infrastructure pattern

Technical Details: The Bucket Consolidation Pattern

The adamcherrycomics.dangerouscentaur.com domain originally followed a per-site bucket pattern common in early multi-tenant AWS deployments:

Old pattern:
├── s3://adamcherrycomics.dangerouscentaur.com/  [origin bucket]
│   └── index.html, assets/, ...
└── Route53: adamcherrycomics.dangerouscentaur.com → CloudFront dist

This pattern was later consolidated into a shared-bucket-with-routing model:

Current pattern:
├── s3://dc-sites/  [shared origin bucket]
│   ├── adamcherrycomics.dangerouscentaur.com/
│   ├── otherproject.dangerouscentaur.com/
│   └── ...
├── CloudFront distribution (ID: E2Q4UU71SRNTMB)
│   ├── Origin: dc-sites.s3.us-east-1.amazonaws.com
│   └── CloudFront Function (dc-sites-router)
│       └── Rewrites: /path → /adamcherrycomics.dangerouscentaur.com/path
└── Route53: adamcherrycomics.dangerouscentaur.com → CF dist CNAME

This consolidation provides several operational benefits: reduced bucket management overhead, unified versioning policies across sites, simpler IAM scoping (one bucket vs. N buckets), and centralized cache invalidation.

Why the Old Bucket Was Safe to Delete

Request path verification: The CloudFront distribution E2Q4UU71SRNTMB has exactly one origin configured: dc-sites.s3.us-east-1.amazonaws.com. All incoming requests to adamcherrycomics.dangerouscentaur.com are rewritten by the dc-sites-router CloudFront Function before reaching S3, transforming a request for /index.html into /adamcherrycomics.dangerouscentaur.com/index.html within the shared bucket.

DNS independence: The Route53 record for adamcherrycomics.dangerouscentaur.com is a CNAME pointing to dclu4nl5nln98.cloudfront.net (the CloudFront distribution edge), not to an S3 website endpoint. This means DNS resolution never touches the per-site bucket name, and removing the bucket has zero impact on domain resolution.

Bucket state verification: A direct S3 API call confirmed Total Objects: 0 — the bucket contained no content, versioning metadata, or access logs. The only resource cost was the monthly bucket fee (negligible) and organizational debt (higher).

# Verification command (no credentials shown):
aws s3api head-bucket --bucket adamcherrycomics.dangerouscentaur.com
aws s3api list-objects-v2 --bucket adamcherrycomics.dangerouscentaur.com

# Deletion:
aws s3api delete-bucket --bucket adamcherrycomics.dangerouscentaur.com

DNS CNAME Shadowing: A Brief Detour

This session also documented a DNS issue fixed in the prior deployment cycle (2026-05-21). The problem illustrates why explicit records matter in wildcard-heavy zones:

The wildcard record *.dangerouscentaur.com pointed to the shared CloudFront distribution. However, the www.adamcherrycomics CNAME was missing at Namecheap. This created a shadowing situation:

Zone: dangerouscentaur.com
├── *.dangerouscentaur.com  CNAME → dclu4nl5nln98.cloudfront.net
└── Missing: adamcherrycomics.dangerouscentaur.com  CNAME

Result: www.adamcherrycomics.dangerouscentaur.com resolved (matched wildcard)
        adamcherrycomics.dangerouscentaur.com did NOT resolve (RFC 1034 §4.3.3)

RFC 1034 §4.3.3 rule: When a wildcard match occurs, a label-by-label search for a more specific CNAME stops if an intermediate node already has a CNAME record. Conversely, if a more specific CNAME exists, it takes precedence over the wildcard match.

Fix applied: Added explicit CNAME records at Namecheap for both adamcherrycomics and www.adamcherrycomics, pointing to the CloudFront edge. This ensures deterministic resolution regardless of wildcard shadowing, and makes the configuration self-documenting for future engineers.

Infrastructure Decisions: Shared Bucket + Router Function Pattern

Why consolidate? The per-bucket pattern (one S3 bucket per site) scales administratively poorly. With even 5–10 projects, you accumulate:

  • N IAM policies scoped to N buckets
  • N bucket-level configurations (versioning, logging, lifecycle, encryption)
  • N CloudFront origins in a single distribution (or N distributions)
  • N DNS records, N SSL certificate SANs, N cache invalidation workflows

The shared-bucket-with-function approach: A single S3 bucket holds all site content, partitioned by hostname prefix. A CloudFront Function (lightweight, runs on every request) performs the URI rewrite. This provides:

  • One origin configuration: Single S3 bucket endpoint, single set of cache behaviors
  • Declarative routing: The router function is version-controlled and human-readable
  • Efficient cache: CloudFront caches the rewritten request path, so /adamcherrycomics.dangerouscentaur.com/index.html in CF cache is separate from /otherproject.dangerouscentaur.com/index.html
  • Cost efficiency: One bucket, one distribution, one set of CloudFront request fees

CloudFront Function vs. Lambda@Edge: We used a CloudFront Function (sub-millisecond latency, no cold starts) rather than Lambda@Edge (higher lat