All cloud projects
LIVE us-east-1 2026
CLOUD PROJECT · 2026

Observability + public status page

A synthetic canary probes the platform every 10 minutes from AWS, emits custom CloudWatch metrics, and publishes a rolling results feed that powers a public, self-updating status page — all same-origin, under the strict site CSP, for roughly zero dollars a month.

CloudWatchSNSLambdaEventBridgeS3CloudFrontTerraform

The problem

A portfolio that claims “reliability-first infrastructure” should be able to prove it. The honest question a hiring manager asks is: how would you even know if this site went down? Without instrumentation, the answer is “a visitor would tell me” — which is the answer of someone who has never run anything in production.

So the goal here isn’t a dashboard for its own sake. It’s the full monitoring loop, end to end: measure the platform from the outside, alert a human when it breaks, and publish the evidence publicly. The constraint that makes it interesting is cost — real synthetic monitoring (CloudWatch Synthetics, Pingdom, Datadog) starts at tens of dollars a month, which is absurd for a site whose entire run-rate is under $2. Everything below stays inside the AWS free tier.

The architecture

A Lambda canary runs on a 10-minute EventBridge schedule. Each run issues an HTTPS GET to three targets — the site, the /api/visits endpoint, and the demos domain — and records three things per target: availability (status code), latency (wall-clock of the request), and, for the HTML targets, whether the expected security headers (HSTS, CSP, X-Frame-Options, Referrer-Policy, Permissions-Policy) are still present.

That data goes two places. It’s published as custom CloudWatch metrics (availability and latency, dimensioned by target), where Terraform-managed alarms watch it and page an SNS topic on two consecutive failed probes. And it’s appended to a rolling ~90-day results document in a dedicated S3 data bucket, served same-origin through a new CloudFront /data/* behavior — which is what the public status page fetches.

EventBridgeCanary LambdaGET / (site)GET /api/visitsGET demos10 minCloudWatchAlarms → SNSmetricsS3 data bucketCloudFront /data/*/status/ pageresults.json
Probe path (top): EventBridge → canary Lambda → three HTTPS targets. Fan-out (bottom): metrics → CloudWatch alarms → SNS email; results JSON → S3 data bucket → CloudFront /data/* → the browser status page.

Key decisions & trade-offs

A Lambda canary instead of CloudWatch Synthetics. Synthetics canaries are the “correct” AWS answer and cost roughly $0.0012 per run — about $5/month at a 10-minute cadence, more than the entire rest of the platform. A hand-rolled Lambda doing the same three GETs costs fractions of a cent. The trade-off is that I own the probe logic (retries, header parsing, the results format) instead of getting a managed screenshot-and-HAR harness. For three endpoints, owning it is the right call — and it’s a better interview story than “I clicked the Synthetics wizard.”

Same-origin data, not a relaxed CSP. The status page is a static page under the site’s strict default-src 'self' policy. Rather than punch a hole in the CSP to reach an external metrics API, the canary writes its results into an S3 bucket that CloudFront serves at /data/* on the same distribution. The page fetches /data/status.json as a first-party request. No new origin, no CSP change, no third-party JavaScript — the security posture the site advertises stays intact.

A dedicated data bucket, because of the deploy hazard. The site deploys with aws s3 sync --delete, which prunes anything in the target bucket that isn’t in the build output. Lambda-written JSON in the site bucket would be deleted on the next deploy. So the canary writes to a separate bucket entirely, wired to CloudFront under its own OAC with a bucket policy scoped to the data/ prefix. The same bucket will back the upcoming FinOps and security-scorecard pages under their own prefixes.

Custom metrics kept under the free-tier line. Two metrics per target across three targets is six custom metrics — inside the 10 that CloudWatch gives for free. Availability alarms fire on the Minimum statistic over two consecutive 10-minute windows, so a single blip doesn’t page me at 3am, but a real outage does within ~20 minutes.

Cost breakdown

ComponentMonthly cost
Lambda canary (~4,400 invocations)~$0 (free tier)
Custom CloudWatch metrics (6)$0 (≤ 10 free)
CloudWatch alarms (5)$0 (≤ 10 free)
SNS email notifications~$0
S3 data bucket + CloudFront /data/*fractional cents
Total≈ $0/mo

What I’d do differently at scale

For more than a handful of endpoints, the hand-rolled canary stops being worth it — CloudWatch Synthetics’ managed screenshots, HAR capture, and multi-step scripted flows earn their fee once you’re monitoring real user journeys rather than liveness. I’d also move from a single-region probe to a few regions to distinguish “the site is down” from “us-east-1 can’t reach it,” and push the alarm fan-out through an incident tool (PagerDuty / Opsgenie) instead of raw SNS email once there’s an on-call rotation to respect. The rolling JSON-in-S3 results store is deliberately the simplest thing that works; at higher resolution it would become a time-series store (Timestream or Prometheus) with the status page querying an aggregation endpoint rather than replaying every sample in the browser.