case study · cloud
architecture.
Whole stack sits in one Terraform state. Site, CDN, DNS, cert, contact form, log
retention — one apply covers all of it. Push to main, plan runs,
apply runs. Cross-region failover, hourly Puppeteer canaries, and Athena over the access
logs are all part of the same apply.
01 · request path
user
│
▼
┌─────────────┐ ┌────────────────┐
│ cloudflare │ │ acm (us-east-1)│
│ dns │ │ wildcard cert │
└──────┬──────┘ └────────┬─────────┘
│ │
▼ ▼
┌──────────────────────────────────────────┐
│ cloudfront (us-west-2) │
│ · origin group (failover on 5xx/403) │
│ · viewer-request rewrite fn │
│ · security-headers policy │
└────┬─────────────────────────────┬───────┘
│ │
GET * │ │ POST /contact
▼ ▼
┌──────────────┐ ┌────────────────┐
│ s3 primary │ │ http api v2 │
│ us-west-2 │ │ api gateway │
└──────┬───────┘ └────────┬───────┘
│ crr (async) │
▼ ▼
┌──────────────┐ ┌────────────────┐
│ s3 dr │ │ lambda │
│ us-east-1 │ │ (node 20) │
└──────────────┘ └──┬────────┬────┘
│ │
▼ ▼
┌────────┐ ┌────────────┐
│ ses │ │ dynamodb │
│ send │ │ audit │
└────────┘ └────────────┘
observability plane
────────────────────
synthetics canary ─ 3 endpoints, hourly, us-west-2 ─▶ cloudwatch alarms
x-ray tracing ─ lambda + api gw + digest lambda ─▶ trace map
eventbridge sched ─ nightly 03:00 utc ─▶ digest lambda
digest lambda ─ synthetics + athena
─▶ json → s3 (primary + dr) → /status /insights
02 · services + purpose
| Service | Purpose | Why |
|---|---|---|
s3 | Origin bucket + DR replica + logs + Athena results. | Private, OAC-only reads. Cross-region replication → us-east-1 for 5-min RTO. |
cloudfront | HTTPS-terminating CDN + edge cache. | Origin group failover, security-headers policy, JS URL rewrite at the edge. |
acm | TLS cert (us-east-1 for CloudFront). | DNS-01 validated via a Cloudflare CNAME. |
api gateway http v2 | Public POST /contact endpoint. | Lighter than REST. CORS enforced at the gateway so Lambda never sees preflights. |
lambda | Contact handler + nightly digest job. | Node 20 + X-Ray active tracing. IAM scoped to a single verified SES sender. |
ses | Sends contact submissions to the owner inbox. | Policy condition on ses:FromAddress prevents impersonation. |
dynamodb | Audit log of every submission + Terraform state lock. | Pay-per-request + PITR + encryption at rest. |
athena + glue | Serverless analytics over CloudFront logs. | Workgroup capped at 1 GB scanned per query. Saved queries as Terraform resources. |
synthetics | Puppeteer-based canary hitting 3 pages hourly. | Screenshots + timing + alarm on SuccessPercent < 100. |
x-ray | Distributed tracing across Lambda + API GW. | Invaluable when the contact form breaks — the request path is right there in the trace map. |
eventbridge sched | Nightly cron for the digest Lambda. | Replaces CloudWatch Events. Cleaner IAM model. |
cloudwatch logs | Lambda + HTTP API access logs. | 30-day retention on every group so nothing quietly creeps up. |
code
read the terraform
Repo's public.
github.com/dram64/showcase.dram-soc.org
— infra/ is the Terraform, site/ is the Astro source,
.github/workflows/ is the deploy pipeline. Read whatever's useful.