Salahuddin Bayassi

ML engineering · 2025

Warden

A self-hosted moderation service that answers in under 50 ms by accepting first and scoring text and images for toxicity and NSFW content in the background.

Role
Solo: design, ML, backend
Stack
FastAPI, RabbitMQ, Celery, PyTorch, Redis, PostgreSQL, MongoDB
Year
2025
Status
Prototype
ingest response, p95
<50ms
pHash fast path for known media
O(1)
models: text toxicity + NSFW vision
2
A grid of moderated comments, each with a toxicity score drawn as a bar

Intended use

Community platforms need to stop harmful posts without making every user wait for a model.

Warden is a plug-and-play moderation service. A client posts text or an image, Warden answers in under 50 ms, and isolated workers score the content in the background. Flagged items are held or removed as soon as a score lands, and the client hears about it over a WebSocket.

It is built for small teams who want moderation as a service they run themselves, not a third-party API with per-call pricing.

Architecture

POST /moderateknown hash?enqueuescoresClient appFastAPI gatewayRedis pHash setRabbitMQtoxic-bert workerNSFW vision workerMongoDB telemetryPostgreSQL state
System diagram: data flows left to right

Decisions

  1. Accept first, judge later. The HTTP path never waits for inference. It validates, enqueues and returns, so a traffic spike slows the queue, not the users.
  2. Hash before you think. Every image gets a perceptual hash checked against a Redis set of banned media. Known spam is rejected in O(1) without touching the GPU.
  3. Two stores for two jobs. PostgreSQL holds the lifecycle of each request; MongoDB takes the noisy per-model confidence telemetry.
  4. Lazy weights. Model weights are baked into the image but loaded on the first task, which keeps idle workers small.

Results & evaluation

ingest response, p95
<50ms
pHash fast path for known media
O(1)
models: text toxicity + NSFW vision
2
Toxicity scores for a batch of comments, sorted high to low
Toxicity scores, one batch
Latency waveform with a p95 threshold line at 50 ms
Ingest latency vs load

Limitations & next steps

  • The p95 figure comes from local load tests, not production traffic.
  • Toxicity models carry the biases of their training data; borderline scores go to a human review queue rather than auto-removal.
  • Next: per-tenant thresholds and a small dashboard for reviewers.
Next project · AI engineeringData-to-Policy