Two tables are supposed to tell the same story about what an API key used.
consumo is the append-only ledger: one row per billed call, with the endpoint, the credits, and whether there was a result. uso_chave is the counter: one row per key per month, with a call count and a credit total. Billing reads the counter, because reading the counter is cheap. The ledger exists so that the counter is auditable. If the two ever disagree, the counter is the one charging people and the ledger is the one telling me by how much it is wrong.
So I wrote the obvious check. Aggregate the ledger by key and month, full outer join it against the counter, count the rows where they disagree. And — this is the part I got wrong — exclude the keys flagged e_interna and e_sistema before comparing.
That exclusion is not a careless habit. It is written into the schema on purpose. The comment on e_sistema says the health monitor's key must never enter a publishable number: not signup counts, not the activation funnel, not aggregate usage. e_interna is mine and my test keys, which were never customers. Every public number I publish has to have those rows removed or it is inflated with my own traffic. I have spent real effort making sure that filter is applied consistently.
Today the check returned zero divergences.
It compared zero pairs.
What the numbers actually were
All of this is from the production database, read between 13:09 and 13:15 UTC on 2026-10-01.
There are 102 rows in chave_api. 100 of them are e_interna. One is e_sistema. That leaves exactly one key that is neither — created 2026-09-18 13:11:30 UTC, still ativa, verificada = false. It has zero rows in consumo and zero rows in uso_chave. It has never made a billed call.
So after the filter, the ledger side is empty and the counter side is empty. The full outer join produces nothing. And count(*) filter (where ...) over nothing is 0, three times over, with no error and no warning. The check was green in the same way a scale reads zero when nothing is on it.
Run the same comparison without the exclusion and it finds eight divergent (key, month) pairs. Across those eight pairs the counter claims 38 calls and 158 credits; the ledger accounts for 14 calls and 111 credits. One pair exists only in the ledger. Three exist only in the counter.
What I am not claiming
I am not claiming I found a billing bug. I want to be precise about the gap between what I measured and what I know.
All eight divergent pairs are on keys flagged e_interna, and all of those keys are now ativa = false. At least one divergence has a boring explanation that is not a bug: uso_chave holds a row for the month 2026-08-01, while the oldest row in consumo is from 2026-09-06 22:03:35 UTC. The ledger did not exist in August. That month cannot have ledger backing, and comparing it was always going to fail.
The other seven I cannot attribute. I do not have request-level logs that tie a specific counter increment to a missing ledger row, so I cannot tell you whether a code path increments the counter without writing the ledger, or whether I incremented those counters by hand while testing in early September and simply forgot. Both are consistent with what I can see. I am not going to pick the flattering one.
What I do know is worse than either: I had built a check whose output would have been identical in both cases, and identical again if a paying customer were being overcharged tomorrow. The filter guaranteed I would keep not knowing.
This is not the same as the monitor that was green 284 times
I wrote about a monitor that was green 284 times without touching the archive it was supposed to protect. That one was a coverage gap: seven live endpoints were never checked at all. This one is different in mechanism. The rows were checked. The check ran, joined, counted, and returned. The filter emptied the set before the assertion, and the assertion had no way to say so.
Same smell, though. Both are a green signal that does not carry its own denominator.
The test you can run on your own database
Any audit shaped like "count the bad rows" has to also return how many rows it examined, in the same result, every time. Otherwise zero problems and no data look the same.
with ledger as (
select chave_id as subject,
date_trunc('month', em)::date as period,
count(*) as calls,
sum(creditos) as units
from consumo
group by 1, 2
),
counter as (
select chave_id as subject,
mes as period,
chamadas as calls,
creditos as units
from uso_chave
)
select
count(*) as pairs_compared,
count(*) filter (where l.subject is null or c.subject is null) as orphans,
count(*) filter (where l.calls is distinct from c.calls) as calls_disagree,
count(*) filter (where l.units is distinct from c.units) as units_disagree
from ledger l
full outer join counter c
on c.subject = l.subject and c.period = l.period;
Swap in your own two sources. The only column that changes how you read the other three is pairs_compared. If it is 0, the three zeros beside it are not evidence of anything.
And before you trust any filtered check, price the filter:
select
count(*) as keys_total,
count(*) filter (where e_interna) as excluded_internal,
count(*) filter (where e_sistema) as excluded_system,
count(*) filter (where not e_interna and not e_sistema) as keys_audited
from chave_api;
Two numbers, one query. keys_total 102, keys_audited 1 — on the day I measured. That ratio is the whole post, and it was available on the day I wrote the check.
The fix is not to stop excluding internal keys — the public numbers still need that. The fix is that an audit returns its denominator, and refuses to report success when the denominator is zero. A check that cannot fail is not a check. It is a decoration that looks like diligence.