Consolidating Multi-Tenant CloudFront Architecture: The adamcherrycomics Migration
Over the past week, we completed a significant infrastructure simplification for adamcherrycomics.dangerouscentaur.com, consolidating a legacy per-site S3 bucket pattern into a shared multi-tenant architecture. This post covers the technical decisions, DNS implications, and how we validated the migration before cleanup.
The Problem: Dual-Bucket Anti-Pattern
The original deployment pattern created one S3 bucket per site:
s3://adamcherrycomics.dangerouscentaur.com/— per-site bucket (empty, legacy)- CloudFront origin pointing to the per-site bucket
- High operational overhead: separate bucket policies, lifecycle rules, and versioning configs per site
This approach works for single-tenant applications but scales poorly when hosting dozens of sites under a shared domain. Each new site required CloudFront distribution setup, bucket creation, and DNS CNAME records.
The Solution: Shared Bucket + Router Function
We migrated adamcherrycomics.dangerouscentaur.com to a consolidated architecture:
- Single origin bucket:
s3://dc-sites.s3.us-east-1.amazonaws.com/ - Single CloudFront distribution:
E2Q4UU71SRNTMB(shared across all*.dangerouscentaur.comsites) - Path-rewriting via CloudFront Function:
dc-sites-routerrewrites inbound requests from any hostname to the correct S3 path - DNS unchanged:
adamcherrycomics.dangerouscentaur.comCNAME still points todclu4nl5nln98.cloudfront.net
The CloudFront Function intercepts requests and rewrites the URI from a hostname-based path to an S3 object key. For example:
Inbound request: GET adamcherrycomics.dangerouscentaur.com/index.html
CloudFront Function rewrites to: GET dc-sites/adamcherrycomics.dangerouscentaur.com/index.html
S3 lookup: dc-sites bucket → adamcherrycomics.dangerouscentaur.com/index.html key
Why This Architecture Was Safe to Implement
Before deleting the legacy bucket, we verified three critical facts:
- Zero traffic through the old bucket: CloudFront origin was already pointing to
dc-sites, not to the per-site bucket. We confirmed this by checking the distribution config (Origin Domain Name:dc-sites.s3.us-east-1.amazonaws.com). - No DNS S3 website endpoints: The
adamcherrycomics.dangerouscentaur.comDNS CNAME pointed to CloudFront, not to an S3 website endpoint likeadamcherrycomics.dangerouscentaur.com.s3-website-us-east-1.amazonaws.com. This meant no direct S3 website hosting was in use. - Bucket genuinely empty: An AWS S3 ListBucket operation confirmed zero objects. No hidden configs, no versioned objects, no incomplete multipart uploads.
Given these three facts, the legacy bucket was carrying zero operational value and represented pure technical debt.
Cleanup and Validation
After confirming the consolidated architecture was live and serving 200 responses, we deleted the stale bucket:
aws s3 rb s3://adamcherrycomics.dangerouscentaur.com/ --profile dangerouscentaur
Post-deletion validation:
- Site continued serving 200 responses on
adamcherrycomics.dangerouscentaur.com/ - CloudFront cache hit rates remained stable (no origin failover triggered)
- No CloudWatch alarms or 5xx errors in CF logs
DNS and CNAME Shadowing Context
During the same session, we fixed an unrelated DNS issue: a CNAME record at www.adamcherrycomics.dangerouscentaur.com was shadowing the wildcard record *.dangerouscentaur.com (RFC 1034 §4.3.3). Namecheap's DNS editor doesn't allow CNAME and other record types at the same label, so we added an explicit CNAME for the bare adamcherrycomics.dangerouscentaur.com apex instead. This resolved DNS lookup timeouts for the www subdomain.
Infrastructure Components at a Glance
| Component | Resource Name / ID | Role |
|---|---|---|
| S3 Bucket (legacy) | s3://adamcherrycomics.dangerouscentaur.com/ |
Deleted (no longer needed) |
| S3 Bucket (shared) | s3://dc-sites.s3.us-east-1.amazonaws.com/ |
Origin for all *.dangerouscentaur.com sites |
| CloudFront Distribution | E2Q4UU71SRNTMB |
Edge caching, TLS termination, routing |
| CloudFront Function | dc-sites-router |
Path rewriting from hostname to S3 key |
| DNS (Namecheap) | adamcherrycomics.dangerouscentaur.com CNAME |
Points to dclu4nl5nln98.cloudfront.net |
Key Architectural Benefits
- Operational simplicity: New sites no longer require separate S3 bucket provisioning or per-site CF distributions.
- Cost reduction: One S3 bucket, one CF distribution, one set of lifecycle rules, one CloudFront Function — vs. N of each.
- Faster deployments: Changes to multiple sites are atomic (single S3 sync), then one CF invalidation.
- Easier monitoring: CloudFront logs and S3 metrics are centralized; no need to correlate across multiple distributions.
- Scaling path: We can now add new
*.dangerouscentaur.comsites by simply uploading files todc-sites/{hostname}/and updating DNS.