Inspiration
Moderation is reactive by nature. A subreddit gets brigaded, spam-flooded, or hit by a coordinated harassment campaign — and mods find out when their inbox is already on fire. By the time a human notices the pattern, hundreds of bad posts or comments may have slipped through, and the community has already been damaged.
The tools that exist today tell mods what happened. ModPulse was built to tell mods what is happening — right now, before it becomes a crisis.
The inspiration came from infrastructure monitoring. DevOps engineers don't wait for their servers to crash before investigating — they watch dashboards, set anomaly thresholds, and get paged the moment a metric spikes. Subreddit moderators deserve the same capability. A brigading event looks exactly like a traffic anomaly: post volume spikes, report rate climbs, new account ratio surges. These are measurable signals. ModPulse measures them.
What it does
ModPulse is a community health monitoring tool for Reddit moderators, built as a Devvit custom post with a real-time WebView dashboard.
It tracks three core metrics continuously:
- Posts per hour — volume of new submissions
- Reports per hour — rate of community reports being filed
- New account ratio — percentage of activity from accounts under 7 days old
Every 30 minutes, ModPulse collects a snapshot of these metrics and stores it using Redis sorted sets. Over 7 days it builds a rolling baseline — the "normal" state of your community.
Anomaly detection fires when any metric exceeds $2\times$ its 7-day baseline AND crosses a raw floor threshold (to prevent false alerts in low-volume communities). When an anomaly is detected, the mod team receives an immediate modmail alert with the metric, current value, baseline, and deviation factor.
The dashboard shows moderators:
- A health score from 0–100 computed from all three metrics
- Real-time sparkline charts (powered by Recharts) for each metric
- Current value vs. baseline for instant context
- A list of the top 3 most-reported active posts with individual lock buttons
- A Crowd Control toggle for instant mitigation during brigades
- A feed of recent anomaly alerts with timestamps
Weekly digests are sent every Monday — a summary of the week's metrics, alert count, and trend direction (improving / stable / degrading).
How we built it
ModPulse runs entirely on Reddit's Developer Platform with no external services:
Event-driven metrics collection — three Devvit triggers feed all data:
PostSubmit→ incrementsmp:post_count:{date}:{hour}in RedisCommentSubmit→ increments comment counter + checks account age for new account ratioPostReport→ incrementsmp:report_count:{date}
Zero API polling. All metrics come from events as they happen.
Redis sorted sets for time-series data — snapshots are stored with Unix timestamps as scores, enabling efficient range queries:
await ctx.redis.zAdd('mp:ts:reports', {
score: timestamp,
member: `${value}:${timestamp}`
});
// Prune data older than 7 days automatically
await ctx.redis.zRemRangeByScore('mp:ts:reports', 0, sevenDaysAgo);
Anomaly detection formula:
$$\text{anomaly} = \text{current} > (\text{baseline} \times 2) \land \text{current} > \text{floor}$$
Where floor = 5 for reports/hour, 10 for posts/hour. This prevents statistical noise from triggering alerts in small communities.
Health score computation:
$$\text{score} = \max\left(0,\ 100 - \sum_{m \in M} \text{deduction}(m)\right)$$
Where each metric $m$ contributes deductions based on deviation from baseline: 0 points under $1.5\times$, 15 points at $1.5\text{–}2\times$, 35 points above $2\times$.
WebView dashboard — a React app in webroot/page.html communicates with
the Devvit backend via typed postMessage contracts. The backend handles all
Redis reads/writes and Reddit API calls; the frontend handles all rendering.
Scheduler jobs registered on AppInstall:
- Every 30 min: collect snapshot + run anomaly detection
- Daily midnight UTC: recompute 7-day baseline
- Monday 9am UTC: send weekly digest modmail
Challenges we ran into
No native time-series storage in Devvit. Redis sorted sets aren't
documented prominently in Devvit's guides — most example apps use simple
key-value storage. Using zAdd/zRange/zRemRangeByScore for rolling
time-series data required reading the raw Redis API surface carefully and
testing edge cases around score-based range queries.
The warmup problem. A monitoring tool with no baseline data is useless — and worse, it will fire false alerts. The first 7 days after install have incomplete baselines. We had to build a warmup state that shows a progress indicator ("Day 3 of 7 — baseline building") and suppresses anomaly alerts until enough data exists to be meaningful.
Duplicate scheduler jobs on reinstall. Devvit's AppInstall trigger fires
on both fresh installs and app updates. Without deduplication, reinstalling
the app stacks multiple cron jobs running the same work. We solved this with a
Redis flag (mp:jobs_scheduled) that prevents duplicate scheduling.
Blind moderation actions. Early designs had a single "Lock Latest Post" button — which could accidentally lock a legitimate post during a noisy report surge. We replaced this with a top-3 most-reported posts list with individual lock buttons, giving mods context before acting.
Accomplishments that we're proud of
- Zero API polling architecture — every metric is captured at event time, making the app efficient and scalable with no rate limit exposure
- The anomaly detection formula handles both large and small communities correctly — the raw floor prevents alert spam on low-volume subs while the $2\times$ multiplier catches genuine spikes at any scale
- The warmup state means the app is honest about its confidence — it doesn't pretend to have a baseline it hasn't earned yet
- Full install-to-insight in one click — AppInstall creates the dashboard, schedules all jobs, and sends onboarding modmail automatically
What we learned
Reactive systems need careful state management. ModPulse processes events asynchronously across multiple scheduler jobs, and we learned early that Redis is the only source of truth — any state that lives only in memory is lost between executions. Every piece of data that matters gets written to Redis immediately.
We also learned that the hardest part of building monitoring tools isn't detecting anomalies — it's reducing false positives. An alert that fires too often trains mods to ignore it. The combination of the $2\times$ multiplier, the raw floor threshold, and the 7-day warmup period exists entirely to make every alert feel meaningful when it arrives.
What's next for ModPulse
- Configurable thresholds — let mods set their own anomaly sensitivity per metric via Devvit install settings
- Keyword spike detection — track when specific words suddenly appear at high frequency in posts/comments (early warning for coordinated campaigns)
- Cross-subreddit correlation — for mod teams running multiple communities, detect when the same new accounts are active across all of them simultaneously
- Historical trend view — 30/60/90 day charts showing long-term community health trends, not just the current week
- Integration with RuleWizard — when ModPulse detects a new-account surge, offer a one-click option to temporarily enable the Anti-Brigading rule from RuleWizard's template library
Log in or sign up for Devpost to join the conversation.