Totally. When I first launched my project, I literally couldn't sleep at night, kept worrying that some bug in my code would spiral into a self-inflicted Denial of Wallet attack by morning. That fear is what pushed me to build the circuit breaker early on. Prevention over detection is spot on.
That's a solid default. I actually set my RSS polling interval to 1 hour, most sources I follow don't update frequently enough to justify anything shorter. Every 10 minutes works too, but you might end up burning cycles on unchanged feeds.
Good question. The short answer: a single global threshold (cosine similarity ≥ 0.7) works surprisingly well for news, but it's not because embeddings handle idioms perfectly — it's because news articles are structurally constrained.
News articles about the same event tend to share named entities (people, places, organizations), numbers, and factual structure even across languages. "EU approves AI regulation" is a factual statement that embeds similarly regardless of language. This is very different from, say, opinion pieces or cultural commentary where idioms and local framing would diverge more.
That said, similarity alone isn't enough. The real reliability comes from non-semantic constraints layered on top:
- Time gap ≤ 18 hours between article and story — prevents "same topic, different month" false merges
- Story age ≤ 36 hours — old stories stop absorbing new articles
- Two-pass design — matching against refined story embeddings (average of recent articles) is more stable than raw article-to-article comparison
Where it does break: regional stories with heavy local context. A Japanese domestic politics article and an English wire service summary of the same event sometimes land just below threshold because the framing is so different. I accept some missed merges there rather than lowering the threshold and getting false positives.
No per-language thresholds so far — the embedding model (Qwen3) seems to normalize well across the languages I cover. But I wouldn't be surprised if that changes when adding languages with less training data representation.
Author here. I built this for 3mins.news, an AI news aggregator covering 180+ sources in 17 languages. The trickiest part was figuring out that articles in different languages about the same event share zero tokens — MinHash/LSH gives
you Jaccard similarity of 0.
Happy to answer questions about the pgvector setup, Cloudflare Workers constraints, or the clustering algorithm tuning.
I built 3mins.news because I was tired of doomscrolling through news apps. I wanted something that would tell me what happened today and then let me go.
The idea is simple: every day, AI scans 30,000+ articles from 180+ sources across 17 languages, scores them on actual global significance (not clicks), and picks 5–7 that matter most. You read them, see "You're all caught up," and you're done. The whole thing takes about 3 minutes.
A few things I spent the most time on:
- The scoring model. Each story gets a 0–10 significance score based on global impact, novelty, disruption potential, and long-term importance. A geopolitical shift that nobody's tweeting about will rank higher than a viral celebrity story. I'm still tuning this — would love feedback.
- Event narratives. Big stories don't start from scratch daily. When something like a trade war or election develops over weeks, the system builds a 4-part briefing (situation → latest → background → outlook) so you get context without re-reading everything.
- Multilingual generation. Summaries aren't translated — they're generated natively in each language. Currently supports EN, ZH, JA, KO, ES, PT, FR, DE, AR, RU, and 7 more. Same stories, same quality across all.
Stack: Next.js on Cloudflare Pages, Cloudflare Workers for the backend, D1 (SQLite) for storage. Fully serverless.
Free, no registration required. There's an optional email digest if you want it in your inbox.