What thirty seconds of checking would have caught
A catalogue of small, boring, real failures — a www that resolves nowhere, a redirect that drops to http, a response that is not actually compressed — each one cheap to see from outside.
None of the failures below is interesting. Not one requires a race condition, an unusual client, or a bad day at your cloud provider. Each shows up in a single request from outside, and each is routinely found weeks later by somebody who was trying to buy something.
This is the catalogue, with the request that finds each one. Run them by hand once; every one of them can be reintroduced later by a change you were not thinking about.
The redirect that quietly drops to http
You add a trailing slash to a URL. The server redirects to the canonical form —
and the redirect target is http://, not https://, because the rule was
written before TLS was terminated upstream, or because the proxy builds the redirect from
X-Forwarded-Proto and nothing upstream is setting it.
The browser follows it, the HSTS header sends it straight back to https, and
everything works. On a client without an HSTS entry — a first-time visitor, a
crawler, an embedded client — there is one plaintext request in the middle,
carrying whatever was in the URL.
curl -sI https://example.com/pricing/ | grep -i '^location'
If a Location starts with http://, you have found it. The reason this
survives so long is that anything reporting only the final status code reports
a 200 — the plaintext hop is in the middle. redirect-chain reports the whole
sequence, hop by hop.
The www that resolves nowhere
You configured example.com. Somebody types www.example.com, because plenty of people and plenty of old
links still do, and there is no A record, no CNAME, and no
answer at all. Not a redirect, not an error page — a DNS failure, which the
browser renders as "this site can't be reached", which reads as your company
does not exist.
The reverse happens too: www resolves and the apex does not.
dig +short www.example.com
dig +short example.com
curl -sI https://www.example.com | head -1
Both names must resolve, both must serve TLS, and one must redirect to the
other. dns-resolution covers the first part continuously,
which matters because this often breaks at a zone edit months after launch
rather than on the day you set it up.
A certificate for one hostname, serving two
Downstream of the last one. www.example.com resolves and redirects correctly,
and its certificate lists only example.com. A browser shows an interstitial before it ever
reaches the redirect, and a non-browser client — a webhook sender, an SDK — just
fails the handshake.
echo | openssl s_client -servername www.example.com -connect www.example.com:443 2>/dev/null \
| openssl x509 -noout -text | grep -A1 'Subject Alternative Name'
Check every hostname you serve, not just the one you use. ssl-cert-expiry and
cert-chain-trust run per hostname for exactly this reason.
Every log line is a favicon 404
A browser asks for /favicon.ico when it has no cached
icon for the origin, which is every first visit and every visit after the cache
is cleared. If it is not there,
that is a 404 per visitor, forever, in your access log and your error tracking.
The cost is not the icon. It is that one path is now a constant background rate in your 404s, and the real ones — the dead link in the footer, the asset that did not make it into the build — are a small fraction of a large number. Whether you notice them depends on somebody having excluded this path from the view they look at.
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/favicon.ico
Same argument for /robots.txt and /sitemap.xml, which robots-policy and
sitemap-health cover, and which also affect crawling.
Compression that stopped happening at the edge
Compression is configured. It is configured on the origin, and there
is now a CDN or load balancer in front that terminates the connection itself: it
may drop the client's Accept-Encoding on the way through, re-request from the
origin without it, or compress only the MIME types in its own default list,
which commonly covers text/html and not application/json. Nobody notices because nothing is broken — the page is just several times
larger than it should be, on every request, particularly on mobile.
curl -sI -H 'Accept-Encoding: gzip, br' https://example.com | grep -i content-encoding
No Content-Encoding line means no compression. Do it for the HTML, the
JavaScript bundle and an API response separately: they are frequently handled by
different rules. compression is the check; page-weight catches the same
problem from the other end, as a number that got bigger.
A homepage frozen for twenty-four hours
Someone sets Cache-Control: public, max-age=86400 on the homepage to make it
fast. It is fast. It is also stale for twenty-four hours in every CDN node and
every visitor's browser, including immediately after you deploy a fix.
The specific pain is that you cannot see it. You are testing with a hard refresh and a warm session; your customers are being served yesterday's document, and when you ask them to reload, they get it again. The worst version of this is on an HTML document that references hashed asset filenames — cached HTML pointing at asset URLs that no longer exist, which is a blank page rather than a stale one.
curl -sI https://example.com | grep -iE 'cache-control|etag|age'
The rule of thumb: hashed assets get a long max-age and immutable; HTML
documents get a short one or no-cache with an ETag. cache-policy watches
that this stays true, because it is exactly the kind of setting that a
performance-minded change reintroduces.
One subresource still on http
The page is served over https and pulls one script, one stylesheet or one
image over http. Browsers block the script silently — the console has a
message and the page does not, so the feature is simply absent for everyone
except the person who has the console open.
curl -s https://example.com | grep -o 'http://[^"'"'"']*' | sort -u
mixed-content is the continuous version. This is a very common outcome of a
copy-pasted embed code.
Headers that only exist on staging
Strict-Transport-Security, Content-Security-Policy,
X-Content-Type-Options. These arrive by configuration, configuration differs
per environment, and the environment where somebody tested is not the one
serving customers.
curl -sI https://example.com | grep -iE 'strict-transport|content-security|x-content-type'
security-headers and csp-policy are the checks. The failure mode is not an
outage; it is that a control you believe is on has been off since the last
infrastructure change.
Run the list, then stop running the list
Every command above needs nothing but curl. Running them once, today, will
probably find something.
The reason not to leave it there is that none of these live in your application code. They live in a proxy config, a CDN rule, a DNS zone, a framework default — places that change without a commit to your repository, and that a migration or a new environment resets wholesale. A green result in March is a fact about March.
HarpyWatch is the boring version of this list: the same requests, made from
elsewhere at a fixed interval, with one row per asset and one
column per check, and an alert when a cell changes colour. You could write all
of it with curl and cron. What you would then own is the part that is actually
work — keeping the check logic correct as your stack changes, deciding what
counts as a failure rather than a blip, and routing the result somewhere a human
reads. That is the difference, and it is a maintenance difference rather than a
capability one. It is also not free of failure: a checker has its own outages,
its own false alarms, and its own list of URLs that goes out of date if nobody
prunes it.
Cite this
The HarpyWatch team. “What thirty seconds of checking would have caught”. The Nest, HarpyWatch, 27 October 2026 UTC. https://harpywatch.com/blog/what-thirty-seconds-of-checking-catches
More from The Nest
The vulnerabilities agents write fresh
Ask an agent for a login flow and you tend to get a ?next= parameter redirected to whatever it contains. It is the obvious implementation, it is an open redirect, and the remedy was documented years before the model was trained.
The certificate an agent provisioned and nobody agreed to renew
An AI agent that ran certbot once did the work correctly and made no commitment about the renewal. The setup is in your repository; the recurring obligation it created is in nobody's calendar.
The debt you take on when a customer tells you first
An outage costs what it costs. Being informed of it by the person it happened to costs something separate, it accrues, and it is charged against the next incident rather than this one.