Inspiration
Reddit moderators deal with thousands of posts daily, but coordinated attacks don't look suspicious at the individual level. Five accounts posting the same domain within three minutes is invisible when you're reviewing one comment at a time. Existing tools rely on keyword blocklists or per-comment flagging, both of which miss the actual signal: coordination between accounts. We wanted to build something that detects the network, not just the node.
What it does
Flux monitors every comment and post in a subreddit and runs them through an 11-signal weighted confidence model. When multiple accounts share domains, Flux builds a graph, scores the cluster, and fires alerts graded by severity.
The confidence score is computed as:
$$C = \min\left(1.0,\;\sum_{i=1}^{11} w_i \cdot s_i\right)$$
The confidence score is a weighted sum of 11 normalized signals, capped at 1.0. Cluster size contributes up to 0.30, similarity up to 0.25, account age up to 0.22, and so on. Clusters scoring 0.80+ trigger HIGH alerts, 0.60+ MEDIUM, 0.40+ LOW. Below 0.40 is suppressed.
It catches four attack patterns: crypto/affiliate spam rings, astroturfing with varied messaging, coordinated raids, and linked campaigns where a bridge account connects multiple clusters.
Everything surfaces in a live dashboard built as a Reddit custom post. Mods see stats, a real-time alert feed, cluster topology graphs, and can ban entire clusters or notify the mod team in one click.
How we built it
The server runs on Hono and listens to Devvit triggers (onCommentSubmit, onPostSubmit). Every submission passes through a flag-score gate, enters a user-domain graph stored in Redis sorted sets, and gets checked for shared-domain partners. When partners are found, Flux computes confidence across all 11 signals and creates a cluster.
The detection pipeline:
Comment → extract domains → flag score gate (< 3 = skip)
→ resolve URL shorteners → update graph → find partners (< 2 = skip)
→ compute 11 signals → confidence gate (< 0.40 = suppress)
→ generate alert → dashboard + Mod Mail + Mod Queue
The client is React 19 rendered inside Reddit's custom post webview. The dashboard uses a multi-panel CSS grid with a collapsible sidebar, stats cards, a confidence gauge (SVG arc with animated stroke-dashoffset), signal breakdown bars, and a cluster topology graph. The graph is custom SVG where domain nodes sit at the center and user nodes orbit at radii based on account age. Newer accounts (higher threat) orbit closer. Connections are animated bezier curves.
Real-time updates use Devvit Realtime (WebSocket). When the server fires an alert, all connected mod clients receive it instantly without polling.
All state lives in Devvit Redis with structured key namespaces: user:{username}:meta, domain:{domain}:users, cluster:{id}:members, alerts:feed. No external databases, no data leaves Reddit's infrastructure.
Challenges we ran into
Reddit's webview iframe sandboxes browser APIs. No window.confirm(), no window.alert(). Every confirmation flow had to be rebuilt as inline React state with AnimatePresence transitions.
The Groq API integration scaffolding for computing semantic similarity and AI-generated content likelihood was not entirely successful due to lack of support right now. Wiring this into the confidence model would catch campaigns that use paraphrased rather than identical messaging.
The onAppInstall trigger only fires on fresh installs, not upgrades. During development, every code change required uninstall and reinstall to get the dashboard post created.
Tuning 11 signal weights to balance precision and recall across four different attack patterns was hard. Account age alone catches bots but misses sleeper accounts. Copypasta catches spam but misses astroturfing. The weighted ensemble needed extensive testing with simulated scenarios to get the thresholds right. We ended up building four distinct demo scenarios (crypto spam, astroturfing, coordinated raid, linked campaigns) that inject realistic data directly into Redis to validate each detection path.
URL shortener resolution adds latency to every comment with links. We had to keep it under 2 seconds with a HEAD-request-only approach and graceful fallback when resolution fails.
Accomplishments that we're proud of
The cluster topology graph. It started as a React Flow node-edge graph and ended as a custom SVG radar visualization where accounts orbit domains by threat tier, with animated connections and a pulsing center glow. It makes coordinated behavior immediately visible in a way that tables and lists can't.
The confidence model actually works. In testing with our four demo scenarios, it correctly clusters coordinated accounts with zero false positives on normal activity. The 0.40 threshold suppresses noise, the three severity tiers give mods appropriate urgency, and bridge account detection catches operators running multiple campaigns.
Zero configuration. Install the app, the dashboard appears, detection starts. No API keys, no config files, no onboarding flow.
What we learned
Building on Devvit Web 0.13 meant working with a platform that handles triggers, Redis, and Realtime differently from typical web frameworks. The event-driven model is powerful but constrained. We learned to work within the sandbox rather than against it.
No single signal is reliable for detecting coordination. Account age catches bots but misses sleeper accounts. Text similarity catches copypasta but misses varied astroturfing. Domain velocity catches spam bursts but not slow campaigns. The ensemble approach is what makes the system work, and the weights matter more than the individual signal implementations.
Designing for Reddit's webview taught us to think about UI differently. No URL routing, no browser dialogs, limited viewport. Every interaction had to be state-driven and every animation had to feel right on first render since there's no page navigation to reset state.
What's next for Flux
Flux currently runs detection signals locally. The next step is integrating LLM-based semantic analysis for the copypasta and astroturfing signals.
The pending actions queue is built on the backend but needs a frontend page. This would let mods review staged bans before they execute, adding a human-in-the-loop step for medium-confidence clusters instead of requiring manual action.
Cross-subreddit intelligence is the long-term goal. If the same cluster is detected across multiple subreddits running Flux, a shared threat feed could warn mods before an attack reaches their community. This would require a coordination layer beyond single-subreddit Redis, but the data model already supports it through the linked clusters mechanism.
Built With
- bun
- devvit-realtime-(websocket)
- devvit-redis
- devvit-web-0.13
- hono
- motion-(framer-motion)
- react-19
- shadcn/ui
- tailwind-css-v4
- typescript
- vite-8
- vitest

Log in or sign up for Devpost to join the conversation.