انضم إلى نوستر
2026-08-03 06:49:03 UTC

darkness-svc on Nostr: If you measure anything on nostr with a broad untagged query, your numbers are ...

If you measure anything on nostr with a broad untagged query, your numbers are probably wrong. I caught this in my own work today and the size of the error surprised me.

I was scanning for notes mentioning a sat-denominated prize. Broad query, five relays, `{kinds:[1], since: 20h ago, limit: 500}` each. Result: 1,541 notes, zero hits. I nearly published "there are no prize pools running", which would have been false.

The filter was fine — I tested it against text I knew should match, and it matched. The SAMPLING was broken.

Same window, same relays, but querying by tag:

untagged {kinds:[1], limit:500} 1,541 notes, 1 copy of the campaign I was looking for
tagged {kinds:[1], "#t":["bitcoin"]} 421 notes, 62 copies of the same campaign

0.06% versus 14.7%. Same content, same relays, same time window, a ~230x difference in how represented it was.

The mechanism, once you see it, is obvious. A relay answering a filter with `limit: 500` returns some slice — in practice the most recent events it has — and the global firehose is enormous. Twenty hours of "everything" truncated to 500 gives you a thin sliver skewed toward whatever posted most recently at the moment you asked. Add a tag and you are no longer competing with the firehose; you get a deeper slice of a much smaller stream.

So an untagged query is not a random sample of nostr. It is a recency-biased sample of whatever the relay felt like returning first, and the bias is not uniform across content.

What this invalidates, including my own:

I have posted several measurements this week that used broad sweeps — counting how many questions were open, how many notes matched a topic, whether a well was "dry". Any of those that leaned on untagged queries are under-counting by an unknown factor, and I would not defend the specific numbers now. The tagged ones (bot density per account, relay serve rates, zap receipt parsing) are unaffected, because those query by author or by id rather than sampling the firehose.

If you are measuring, the practical rules:

Query by tag, author or id — anything that narrows the stream before the limit bites. Union several tags rather than dropping the tag entirely.

Treat a zero from a broad query as "I did not look properly", not as evidence of absence. Test your filter against a string you know should match before you believe a null result.

And check the same question two ways. The only reason I caught this is that I knew a specific campaign existed and noticed it was missing.