System Status

Live health of every project in this portfolio, checked automatically every 30 minutes by an event-driven pipeline — Step Functions, EventBridge, SQS with a dead-letter queue, and DynamoDB.

Loading...
// fetching current status
How this works: an EventBridge schedule triggers a Step Functions state machine every 30 minutes. It reads the list of monitored targets from DynamoDB, checks each one in parallel (a Map state), and records the result. If a check fails, the workflow routes the failure to an SQS queue — backed by a dead-letter queue for messages that can't be processed — which a Lambda function consumes to send an SNS email alert. Health check history is kept for 7 days via a DynamoDB TTL.
Step Functions EventBridge Scheduler SQS + DLQ SNS DynamoDB (TTL)
architecture decisions
ADR-001 Targets stored as data, not hardcoded +

Decision: the list of monitored URLs lives in a DynamoDB table, read at the start of every execution — not embedded in Lambda code or the state machine definition.

Why: this pipeline is meant to monitor every future project in this portfolio, not just the ones that existed when it was built. Adding a target means adding a row, not shipping new code. The Step Functions Map state iterates over whatever it finds at runtime, so the orchestration logic never needs to change as the portfolio grows.

ADR-002 A "down" result is a Choice, not a Catch +

Decision: when a health check finds a site unreachable, the workflow routes through a Choice state to an alerting path — it does not raise an exception caught by Step Functions' error handling.

Why: a monitored site being down is an expected, normal outcome of a health check — not a failure of the pipeline itself. Retry logic is reserved for genuine infrastructure problems (Lambda throttling, transient AWS errors), never for "the thing I was checking failed the check," which is the entire point of running the check.

ADR-003 30-minute interval, not 5 +

Decision: the pipeline runs every 30 minutes, not every 5.

Why: at 5-minute intervals, monthly Step Functions cost was estimated around $1.65 — already low, but unjustified for a portfolio status page with no real SLA to uphold. At 30 minutes, cost drops to roughly $0.20/month. The trade-off is a detection window of up to 30 minutes before an outage is caught, instead of 5 — acceptable here, since this isn't monitoring a system with contractual uptime guarantees.

ADR-004 7-day TTL on health check history +

Decision: individual health check records expire automatically after 7 days via a DynamoDB TTL attribute, rather than accumulating indefinitely.

Why: at this check frequency, unbounded retention would add roughly 100 rows per target per day with no benefit — the status page only ever needs recent history to compute uptime percentage and show current state. TTL deletion isn't instant (up to ~48 hours after expiry), which is irrelevant for this use case.

ADR-005 Standard Step Functions workflow, not Express +

Decision: the state machine runs as a Standard workflow.

Why: Express workflows are cheaper at high volume, but this pipeline runs infrequently by design. Standard workflows provide a detailed, visual execution history in the console — genuinely useful when debugging why a particular run behaved a certain way — and the cost difference at this volume is negligible.