Back to Projects

Web Page Change Alerts

Python Terraform AWS SES Route 53 IAM Amazon S3 DynamoDB Proxmox LXC Jenkins cron SMTP DKIM/SPF/DMARC
Change watcher architecture

Sources are reduced to comparable lines, diffed against stored state, and mailed only when they change.

The Challenge

Tickets for a one-night cinema event go on sale without warning and sell out the same evening. The venue publishes no feed and no API: a listings page, a monthly PDF and a third-party ticketing system, each updated whenever staff get to it. Watching by hand meant refreshing three pages all day and still missing the moment.

An alert is only useful if it is both fast and quiet. Polling every few minutes is easy; doing it without generating noise that gets ignored, and without the mail landing in a spam folder, is the actual problem.

The Solution

A small Python service fetches each source, reduces it to the lines a reader would care about and compares them with the previous run. Mail goes out only when something differs, so a five minute interval stays readable. Text pages are compared as visible text; a downloads page is compared as hyperlinks, because a new month is published as a PDF whose filename carries the date. The ticketing feed is watched separately, since the listing appearing and tickets actually going on sale are different events.

Delivery mattered as much as detection. A new sending domain was verified in SES with DKIM, SPF and DMARC published through Terraform, so alerts are signed and reach the inbox rather than spam. The sender is a dedicated IAM user permitted to send from exactly one address and nothing else; its access key is created outside Terraform so no live credential is written into state.

It ran every fifteen minutes on a 256 MB container and caught both the new month and the event itself within fifteen minutes of publication.

Implementation Details

The watcher is standard-library Python: no SDK and no dependencies, so the container needs only python3. SES normally implies an AWS SDK; instead the SMTP password is derived from the IAM secret with the SES signing algorithm, so the host holds one send-only credential and nothing else. A first run stores a baseline and deliberately sends nothing. Fetch failures are logged rather than mailed, because a transient timeout is not news, while a source failing for a day is reported in the next real alert.

The infrastructure is Terraform: the SES identity, its DNS records and the IAM user. It was also the first stack in this estate to use durable remote state in S3 with DynamoDB locking, which became the template for migrating the rest; the existing pipeline kept state in a build workspace that was wiped after every run. Applies go through the same Jenkins job as the other environments, extended to handle AWS stacks alongside the existing ones.

Because the need was seasonal, teardown was designed in from the start: every resource carries project and teardown-by tags, the stack holds its own state so it can be destroyed without touching anything else, and a scheduled one-shot job stops the service and removes its own schedule. A scrubbed, general-purpose version is published under the MIT license.