Skip to main content
Jonathan Andrei
Back to all posts
May 20269 min read

Giving a Mod Team a Memory

Reddit's modqueue treats every moderator as a lone agent clearing an inbox. The hardest part of moderating isn't volume, it's the isolation of the borderline call, the inconsistency that creeps across a team, and the judgment that walks out the door when a veteran leaves. Memex is the memory that's missing.

Devvit WebRedditModerationReactRedis

Reddit's modqueue treats every moderator as a lone agent clearing an inbox. But the hardest part of moderating isn't volume. It's the isolation of the borderline decision (the 2 a.m. 'is this over the line?' call you make alone), the inconsistency that creeps in across a distributed team, and the institutional knowledge that walks out the door when a veteran mod leaves.

The CHI 2026 study of how mods actually use the modqueue put numbers to it: 84% of mods leave the queue to gather context, and teams constantly collide and re-litigate the same calls. So I built the thing that's missing. Not a faster inbox, a memory for the team.

Most mod tools make one mod faster at clearing a queue. Memex makes the team decide consistently over time, and stops that knowledge from walking out the door.

It installs as a single Devvit app. There's nothing to configure to start: pick a quorum size if you want, and Memex begins recording every team decision into a shared memory from the first call. No external service, no account, no cost.

Decision DNA: how did we rule on this before?

On any post or comment, Memex shows how the team has historically ruled on similar content: the dominant outcome, a consistency score, and the closest past decisions with the reasons mods gave. You can pull it up three ways: straight from the mod menu on any item, live inside a Conclave room, or by pasting any phrase into the Rulebook's 'test a phrase' tool.

Decision DNA popped up from the mod menu on a native Reddit post, showing a dominant REMOVE outcome
Decision DNA straight from the mod menu on a live post: dominant outcome, consistency, and the similar decisions on record.

The clever part is that low consistency is itself a signal. A 50/50 split isn't noise, it's the system telling you this is genuinely borderline and deserves a team decision rather than a lone call. The whole engine is local: trigram and token Jaccard similarity, batched against per-subreddit Redis with mGet. It works across post types, including link posts, where the domain is folded in so repeat spam and affiliate domains get recognized. No external API, no API key, no per-comment cost, and no ML training on Reddit data. It runs the instant it's installed, on a 200-member sub or a sub with millions, in any language.

Conclave: borderline calls become team votes

Borderline items become mod-only async decision rooms. Mods vote Remove, Keep, Warn, or Escalate; when quorum is reached the consensus action auto-executes for reversible actions. Votes, the quorum meter, and a 'who's reviewing' presence indicator update live for everyone in the room. Because it's async, a borderline post gets a fair team decision without everyone needing to be online at once, which is exactly the reality for a team of 5 mods spread across time zones.

A Memex Conclave decision room showing a crypto-spam post routed for a team vote
A Conclave room: a crypto-spam post auto-routed on the keyword 'crypto', with Decision DNA and Remove / Keep / Warn / Escalate voting.

The Living Rulebook: memory you can search

Every resolved decision becomes a precedent. The Living Rulebook is a custom post showing the team's applied rules, not just the written ones: impact stats, a proportional outcome bar, a 14-day activity view, the open conclaves, and recent precedents. The 'test a phrase' box lets a mod paste any content and instantly see the team's Decision DNA for it before they act.

The Memex Living Rulebook with impact stats, a 14-day activity view, outcome bars, and a test-a-phrase tool
The Living Rulebook: 21 decisions, a 14-day activity view, per-outcome bars, and the 'test a phrase' tool with real example chips.

Calibration and the Sweep

  • Calibration: new mods cast shadow votes that don't count toward quorum; a weekly digest shows exactly where they diverged from team consensus, so they learn the team's standards in weeks instead of months.
  • Consistency Sweep: on demand or on a schedule, Memex audits recent live posts and flags ones similar to content the team removed before but is still up, using the team's own past decisions as the baseline. Flagged items are reported into the modqueue, never auto-removed.
  • It learns from every native mod action too: each manual remove or approve becomes a precedent, so the memory grows even when the team never opens a Conclave.
A weekly calibration digest in modmail showing where a new mod diverged from team consensus
The weekly calibration digest in modmail: agreement with consensus, and exactly where the new mod diverged.

Safety is a setting, not a hope

Bans never auto-execute. They surface as a recommendation that requires a human click, per Reddit's 2026 admin policy on ban bots. The quorum size, the vote window, and auto-routing rules are all explicit settings, with 'escalations never auto-ban' defaulting on. A tool that takes moderation actions on a community has to make its guardrails visible and configurable, not buried in code.

Memex settings: auto-routing, escalations-never-auto-ban, scheduled sweep, and the optional semantic-matching toggle
Settings: auto-routing, escalations-never-auto-ban (on), a scheduled sweep, and the optional semantic matching toggle (off by default).

The hard part: rebuilding the whole app, days from the deadline

I did the entire hackathon on Devvit Blocks. Every feature, every test, the whole front end. Then, late in the build, a community helper (fsv, big.wheel on the Devvit Discord) flagged it directly: the Blocks custom-post renderer is being retired. Custom posts disabled June 30, 2026, and no new Blocks custom-post apps approved. The thing I'd spent the whole hackathon on was going to stop working, and as a brand-new app I had no grandfathered approval to fall back on.

Credit where it's due: fsv (a Devvit community helper) caught this and pointed me to the official notices. Worth a read if you build on Devvit:

So days before the deadline, I made the call to rebuild the entire front end on Devvit Web and re-platform the server, porting the whole decision engine across intact. It was the most stressful stretch of the build, but I'd rather submit something that still runs after June 30 than something polished that doesn't. I kept the original Blocks version on a separate branch for reference.

The forced rewrite made Memex better. Devvit Web's real server runtime is what unlocked the optional semantic layer (embedding calls live server-side); the stricter TypeScript template caught latent bugs in the port; and the webview gave the Living Rulebook a far richer UI than Blocks could render. The deadline emergency turned into the project's biggest upgrade.

The stack now: a React 19 + Tailwind webview over a Hono server, with state in per-subreddit Redis. A single custom-post type renders an inline splash card in the feed and an expanded webview; the server classifies each post (Conclave vs Living Rulebook) and returns the right snapshot. The Decision DNA engine stays local by default, batched against Redis with mGet.

Historical, for the curious only: these show the pre-migration Devvit Blocks build (the deprecated UI, not the current app). The current demo is at the top of this post.

The Devvit Web gotchas

  • Data-access model flip: Blocks passed context.redis / context.reddit into every function; Devvit Web exposes module-level redis / reddit / context from @devvit/web/server. Every persistence and Reddit-API call had to be reworked.
  • reddit.getCurrentSubredditName() doesn't exist on Web (it's only in a doc example). The current subreddit comes from context.subredditName / context.subredditId. Found by reading the shipped type defs, not the prose docs.
  • Branded Thing-IDs: getPostById / getCommentById now require t3_ / t1_ template-literal types, so stored string IDs needed T3() / T1() helpers.
  • Form-data round-trip: a menu action and its form submit are separate requests, so I park the half-built routing input in Redis keyed by the moderator and reclaim it on submit.
  • Stricter TypeScript: the Web template enables noUncheckedIndexedAccess and exactOptionalPropertyTypes, which caught several latent index/optional bugs during the port.

I validated the final devvit.json against Devvit's own bundled config parser, and got type-check, ESLint, the Vite build, and all 50 tests green.

The optional semantic layer

The new server runtime let me add an opt-in semantic layer: paste an embedding API key and Memex auto-detects the provider from its shape (OpenAI or Google Gemini), blends embedding cosine on top of the local score, and caches vectors in Redis. It's off by default and never calls out without a recognized key, so the app stays error-free out of the box. That's the design rule I kept throughout: every external dependency has to degrade gracefully to nothing.

Why it's defensibly different

The 'shared mod workspace' space is crowded. The institutional-memory layer is not. No other Devvit app surfaces how your team decided on similar content at decision time, scores decision consistency, or calibrates new mods against the team's real pattern. The voting and live updates are the delivery mechanism; the memory is the moat. Plus the quieter touches: native Reddit mod-notes on every team decision, and learning from every manual action so the memory grows on its own.

What I learned

The bottleneck in moderation isn't reading speed; it's decision legitimacy and team coherence. Reframing from 'make one mod faster' to 'give the team a memory' produced a tool mods actually want. And building on a platform mid-transition taught me to trust the shipped type definitions over the prose docs, and to design every external dependency so the app degrades gracefully without it.

Try Memex on your subreddit

Memex is live and free to install. It runs the instant it's added, with nothing to configure to start.

Related project

Memex: Institutional Memory for Reddit Mod Teams

View the project