HonestHook

Sign in

Blog ·

My uptime monitor was green 284 times and never touched the archive it is supposed to protect

I sell an API over two things: passthrough profile lookups on social platforms, and a historical archive of what gets attention on developer platforms, hour by hour. I also run an internal monitor that checks my own routes every hour and writes one row per check. I counted what those checks actually cover, against the catalogue of endpoints I charge for. The monitor had been green for a day straight, and the half of the product that holds 256,070 rows had not been checked once.

All numbers below were read on 2026-09-21 between 13:16 and 13:25 UTC, from the production database, and re-counted against the same window on 2026-09-22 before publishing. "The last 24 hours" means the 24 hours before that first reading.

The count

The check ledger (checagem_rota) holds one row per route per monitor run. 1,716 rows at the time of the reading, 288 of them in the last 24 hours. By status:

status cached rows
200 false 278
200 true 6
451 bloqueado false 2
404 nao_encontrado false 1
503 indisponivel false 1

284 of 288 returned 200. Four did not: two 451s and one 503 on medium/profile, one 404 on instagram/profile. By any dashboard convention this is a healthy day — the kind of number that stops you looking further.

The join that spoiled it

My priced catalogue (endpoint) has 23 rows, 19 of them ativo = true, meaning a route exists and answers. The monitor checked 12 distinct endpoints in the window. So seven live endpoints got zero checks:

account
archive/coverage
archive/movers
archive/trends
github/repos
profile/history
threads/posts

Three of those seven are the archive routes — archive/coverage, archive/movers and archive/trends. They read the historical series — 256,070 observations across 360 hourly windows — the only part of this product a competitor cannot rebuild in an afternoon, and the most expensive route I sell: 10 credits for archive/movers against 1 for a profile lookup. Zero of 288 checks touched any of them. A fourth unchecked route, profile/history, also serves a historical series, but a different one: profile snapshots, in their own table. It is not part of the 256,070.

The 12 that were checked are all passthrough profile and post routes — real endpoints, worth watching, and the cheap half. Each gets 24 checks a day. The expensive half gets none.

Those same 12 are, exactly, the rows on our public uptime page. That page answers how well the checked routes answered. Which routes are in the set at all is what this post is about, and the two questions are not the same one.

The second surprise, from the other direction

The 12 checked endpoints break down into 10 platform prefixes. My collection catalogue (plataforma) has 22 rows, 9 with ativo = true — the nine sources the archive is actually built from. Crossing the two lists:

checks in 24h where they went
24 a platform that is live in the collection catalogue (github only)
168 platforms switched off for collection (bluesky, instagram, mastodon, pinterest, tiktok)
96 prefixes that do not exist in the platform table at all (linktree, medium, soundcloud, threads)

This has an innocent explanation, and I will give it before someone else does: a passthrough profile route does not need the platform to be a collection source. Looking up a Medium profile on request and archiving Medium hourly are different jobs. The two tables are allowed to disagree.

What is not innocent is what the green signal then means. Nothing in checagem_rota says which half of the product a row belongs to, so 288 green rows read as "the API is fine" when what they establish is "12 passthrough routes answered". Of the nine sources the archive sells, exactly one appears anywhere in a day of checks.

What kept this from being an outage

A different mechanism does watch the nine sources. The collection ledger (coleta) recorded 780 attempts in the same 24 hours — 90 per platform, 60 for the one topic-excluded pair — with estado = 'ok' on all 780 and not a single vazio or erro. The archive is genuinely healthy, and I knew that from a table the route monitor does not read.

So the failure was not an undetected outage. It was two health signals with no relationship to each other — one loud, covering the cheap half; one quiet, covering the valuable half. On a day when both are fine that costs nothing. It costs on the day only one of them is.

There is a smaller version of the same mistake one column over. endpoint.monitoravel is a boolean meaning "this endpoint may be the target of a recurring check". Three endpoints have it set: archive/movers, archive/trends, profile/history. Checks against those three in the last 24 hours: zero. The intersection between "declared monitorable" and "actually checked" is empty in both directions — every one of the 12 endpoints being checked has monitoravel = false. The flag was written for a customer-facing feature that has never run (monitor_execucao: 0 rows all time) — a fair reason for it to be idle, and none for it to be named the way it is.

What I am not claiming

Reproduce it on your own API

If you have a priced route catalogue in one table and a check ledger in another, this is one query:

-- live endpoints your monitor is not checking
select e.id, e.creditos,
       count(c.id) as checks_24h
from endpoint e
left join checagem_rota c
       on c.endpoint_id = e.id
      and c.em > now() - interval '24 hours'
where e.ativo
group by e.id, e.creditos
order by checks_24h, e.creditos desc;

Read the top of the list. If your most expensive route is also your least checked one, your monitoring was built in the order the endpoints were written rather than the order they matter — which is the default, because nobody chooses it.

The fix I have chosen is not another alert. It is a column on the check ledger saying which half of the product the row belongs to, so that "green" has to name what it covers before it counts.

Trend data with a memory

Every social API answers what’s trending now, then throws it away. HonestHook keeps the hourly archive, so you can ask what gained traction.

Free key, 1,000 credits a month, no card →