Design problems
AI-era systemsHardSDE-2 35 min

Design an AI content moderation pipeline

Asked at
DiscordGoogleJioHotstarMetaOpenAIShareChat

The interviewer asks

“Design the moderation system for a short-video and posts app with 30M new posts and 200M comments a day in 15 Indian languages. Harmful content must be caught quickly, good content must not be wrongly removed, and the system must use ML and LLMs while keeping humans in the loop.”

What a strong answer looks like

A strong answer designs a cascade, not a single model. Cheap, precise checks run first and synchronously: hash matching against known illegal media, blocklists, account trust, and fast classifiers that decide within a few hundred milliseconds whether a post can go live. Heavier analysis runs asynchronously: video frames, speech-to-text, OCR on images, and a multimodal LLM that reads the written policy for borderline cases. Content goes live in limited reach first and is only eligible for wide distribution after deeper checks, and anything that suddenly goes viral is re-checked. Uncertain and reported items go to human review queues prioritised by severity × expected reach, staffed by language. Every decision is logged with the policy version and model versions, users can appeal, and reviewer labels flow back into training and evaluation. Strong candidates set thresholds per policy from precision/recall trade-offs, plan reviewer capacity with numbers, and handle adversarial evasion and legal takedown deadlines.

Concepts to mention

moderation cascade ordered by costperceptual hash matching for known illegal mediaper-policy thresholds from precision/recalllimited reach vs wide distributionreach-aware re-review at view milestonesLLM/VLM judge reading written policy for borderline itemshuman review queues prioritised by severity × reachappeals and audit log with model and policy versionsfeedback loop: reviewer labels → training and evaluationadversarial evasion: OCR, ASR, text normalisation

1 Requirements

Functional

  • Moderate posts (text, images, short video with audio) and comments before and after publishing
  • Policies: child safety, nudity, violence, hate speech, harassment, spam/scams, misinformation, self-harm; each with its own action
  • Actions: allow, block, reduce reach, age-gate, add label, remove, strike or suspend the account
  • User reports and human review queues with a review tool, per language
  • Appeals: creators can appeal; a different reviewer decides
  • Legal requests (court or government orders) handled with audit trail and deadlines
  • Policy changes (e.g. new election-period rules) can be rolled out within hours

Non-functional

  • Synchronous gate: comments p95 < 150 ms, posts p95 < 1 s (images) before going live in limited reach
  • Async deep checks complete p95 < 5 minutes; before content gets wide distribution
  • Known illegal media (hash match) blocked 100% before anyone else sees it
  • Scale: 30M posts/day (peak ~1,000/s) and 200M comments/day (peak ~7k/s)
  • Precision targets per policy, e.g. auto-remove for hate speech only above 95% precision; recall measured weekly on sampled data
  • Every decision explainable and auditable: which signal, model version, policy version, reviewer

Out of scope (say it out loud)

  • Live-stream moderation (mention how it differs)
  • Direct messages (end-to-end encrypted)
  • Ads policy review
  • Writing the policies themselves

2 Estimates

Content rate~350 posts/s and ~2,300 comments/s avg; ~3× at peak30M ÷ 86,400 ≈ 350/s; 200M ÷ 86,400 ≈ 2,300/s; evening peak and cricket matches ≈ 3×
Video frames to classify~4,000-5,000 frames/s~40% of posts are video = 12M/day × ~30 s × 1 frame/s ≈ 360M frames/day ÷ 86,400 ≈ 4,200/s, plus scene-change frames
GPU for vision models~15-25 GPUsAssume an efficient image classifier processes ~500-1,000 frames/s per GPU (batched); 4,200 × 3 peak ÷ ~700 ≈ 18 GPUs, plus OCR and ASR pools
LLM/VLM policy checks~3-5M calls/dayOnly borderline items go to the LLM: ~5% of posts (1.5M) and ~1% of comments (2M) ≈ 3.5M/day ≈ 40/s average
Human review volume~300k items/day~0.4% of posts escalated (120k) + ~150k user reports after dedupe + appeals ~30k ≈ 300k/day
Reviewer headcount~450-500 reviewers on shift per dayA reviewer handles ~600-800 short items per shift (fewer for video); 300k ÷ 700 ≈ 430 reviewer-shifts/day, plus QA sampling and leave → ~500, split across ~15 languages
Decision log~250M rows/day, ~5 TB/yearOne decision record per item (~60 bytes compressed of ids, scores, versions) × 230M items ≈ 14 GB/day ≈ 5 TB/year

3 API

EndpointWhat it does
gRPCModeration.CheckSync(content_id, type, text, media_refs, author_id)Called by post and comment services before publishing. Returns allow | allow_limited | block | hold, with reason codes. Deadline 150 ms for comments, 1 s for posts.
POST/v1/reportsUser reports a post/comment/account with a reason; deduplicated per content and fed into review priority.
GET/v1/review/queues/{queue}/nextReview tool fetches the next item for a reviewer (language and policy skills matched).
POST/v1/review/items/{item_id}/decisionReviewer decision: policy, action, notes. Idempotent per (item_id, reviewer_id).
POST/v1/appealsCreator appeals a removal; routed to a different, senior reviewer.
POST/v1/legal/ordersTrust & safety team records a legal order with deadline; triggers immediate action and audit.

4 Data model

moderation_decisionsCassandra (or DynamoDB)
content_id (partition key)decided_at (clustering)stage (sync|async|human|appeal|legal)actionpolicyscores (map)model_versionspolicy_versionreviewer_id

Append-only history per content item; very high write volume and simple key lookups suit a wide-column store. Current state = latest row.

known_bad_hashesIn-memory index service (FAISS/Hamming search) + Postgres master list
hash (PDQ 256-bit / video hash)categorysource (internal | industry list)added_at

Perceptual hashes match resized or re-encoded copies by Hamming distance (e.g. ≤ 31 bits for PDQ). Kept in memory on each matcher for < 10 ms lookups.

review_itemsPostgres (partitioned by queue)
item_idcontent_idqueue (policy × language)prioritysla_due_atstatusassigned_tolease_untilcreated_at

Work queue with leases; SELECT ... FOR UPDATE SKIP LOCKED hands items out without double assignment. Priority updated as reach grows.

author_trustRedis (online) + data lake (offline)
author_id → trust_scoreaccount_agestrikesrecent_removalsverified

Used as a feature and for routing: new accounts with prior strikes get stricter thresholds.

content_eventsKafka
content.createdmoderation.signalmoderation.decisioncontent.reach_milestone

Keyed by content_id so all signals for one item are processed in order by the decision engine.

labelsData lake (Iceberg on S3)
content_idpolicylabelsource (reviewer|appeal|qa)languagereviewer_agreementpolicy_version

Training and evaluation data; golden sets for reviewer QA come from here.

5 Architecture

CLIENTSEDGESERVICESASYNCDATApost / reportCheckSynchash matchcontent.createdframes, OCR, ASRread mediasignalssignals, reachborderline onlydecision logescalateenforce actionnext item, decidelease itemshuman decisionsCreator / viewer appReviewer consoleAPI gatewaySync gate (hash +fast ML)Post / commentserviceDecision engine(rules)Review serviceKafka: content eventsLLM/VLM policy judgeMedia analysis (GPU)Known-bad hash indexDecisions (Cassandra)Review queues(Postgres)S3 media
ClientEdge / gatewayService / workerQueue / streamCacheDatabase / storageAI / modelThird partyrequestasync (event / queue)

Hover a box to highlight its connections.

6 Request flows

A new video post

  1. 1The creator uploads to S3 via a pre-signed URL and submits the post; the post service calls CheckSync with the caption, thumbnail and author id.
  2. 2The sync gate computes perceptual hashes of the thumbnail and a few keyframes and matches them against the known-bad index; a match blocks the post, preserves evidence and alerts the child-safety team.
  3. 3Fast models score the caption (multilingual text classifier) and thumbnail (image classifier); author trust adjusts thresholds. Result: allow_limited (visible to followers and the author, not to the recommendation feed).
  4. 4content.created goes to Kafka. Media workers sample 1 frame/s and on scene changes, run the image classifier and OCR on frames, and transcribe the audio with a multilingual ASR model; each produces signal events.
  5. 5The decision engine combines signals with per-policy rules: e.g. violence score 0.97 → remove; nudity 0.6-0.9 → send to the VLM judge; all scores low → mark eligible for wide distribution.
  6. 6For borderline items the VLM judge gets the relevant policy text, transcript, OCR text and keyframes and returns {policy, violation: yes/no/unsure, evidence}. 'Unsure' or conflicts with the classifiers go to human review.
  7. 7The decision is written to Cassandra with model and policy versions; the post service applies the action and notifies the creator with the reason and an appeal link.

A post goes viral and gets reports

  1. 1The feed system emits reach milestones (10k, 100k, 1M views) to Kafka; each milestone re-runs the decision with a stricter, reach-aware threshold.
  2. 2User reports are deduplicated per content; reports from trusted reporters weigh more than mass-report brigades from new accounts.
  3. 3The review item's priority = severity of the suspected policy × predicted reach in the next hour, so a misinformation video spreading during an election jumps ahead of an old spam comment.
  4. 4A Hindi-speaking reviewer gets the item with the transcript, highlighted frames and model reasons; decides within the SLA.
  5. 5The decision is enforced, logged, and added as a training label; if it disagrees with the auto-decision, it is also added to the evaluation set for that model.

7 Deep dives

The cascade: cheap and precise first, expensive and smart last

Running a multimodal LLM on 230M items a day would be slow and very expensive, and unnecessary: most content is obviously fine. A cascade orders checks by cost. Stage 1, nearly free: hash matching for known illegal media, blocklists of URLs and scam phone patterns, rate and account signals (a 1-day-old account posting 200 comments with links). Stage 2, cheap ML: small text classifiers per policy (multilingual transformers distilled to run in a few milliseconds on CPU) and image classifiers on GPU. These produce calibrated scores. Stage 3, expensive: video frame analysis, ASR and OCR for text hidden in images and audio, then an LLM or vision-language model that reads the actual policy text and the evidence, only for the ~5% of items in the uncertain band. Stage 4, humans, for the items the models disagree on, high-reach items and appeals. Each stage can only make confident decisions; everything else moves down. Because the LLM reads the written policy, a new policy (say, deepfake rules during elections) can be enforced within hours by updating its prompt, while classifiers are retrained over the following weeks using the labels the LLM and reviewers produce.

Thresholds per policy, not one magic number

Each classifier outputs a score, and the action depends on two thresholds per policy: above the high threshold auto-action, below the low threshold allow, in between escalate. The right thresholds differ by policy because the costs differ. For child sexual abuse material, missing one item is unacceptable, so the low threshold is very low and false positives are accepted (they go to specialised reviewers). For hate speech or harassment, wrongly removing a political opinion has real costs, so auto-removal only happens above ~95% precision and the band for humans is wider. Thresholds are set from data: take a labelled sample per language, plot precision and recall against threshold, and pick points that meet the policy's precision target and the review team's capacity (a wider band means more human work). Re-check per language: a model trained mostly on Hindi and English may be badly calibrated on Tamil or Bhojpuri, so measure each language separately and route low-resource languages to humans more often. Recall cannot be measured from removals alone; sample allowed content randomly each week and have reviewers label it to estimate what was missed.

Reach-aware moderation and the limited-reach state

Harm grows with views. A borderline post seen by 20 followers is a small problem; the same post shown to 2M people through the recommendation feed is a big one. So the system separates 'published' from 'distributed'. After the sync gate, content is visible to the author and followers (limited reach) within a second, which keeps creators happy. It becomes eligible for the recommendation feed only after the async checks pass, typically within minutes. Then reach milestones trigger re-evaluation with stricter thresholds and, at very high reach, a mandatory human look for sensitive categories (news, health claims, communal topics). This is a strong design point because it removes the false choice between 'check everything slowly before posting' and 'post first and hope'. The same idea drives review priority: severity × predicted reach, with SLAs from minutes (imminent harm, legal orders with hour-level deadlines under India's IT Rules) to a day (low-severity spam).

Adversaries, feedback loops and auditability

Bad actors adapt: they add noise or borders to images to beat hashes, write 'f r e e 5 0 0 0 r s' or use look-alike Unicode characters, put scam phone numbers inside images, or mass-report a rival creator. Defences: perceptual (not cryptographic) hashes with a Hamming-distance threshold; text normalisation (Unicode folding, transliteration, removing separators) before classifiers; OCR and ASR so text in images and audio is moderated like captions; report weighting by reporter accuracy history to blunt brigading; and network signals (many accounts posting near-identical content). Every decision row stores model versions, policy version, scores and who decided, so you can answer 'why was this removed?' for an appeal, a regulator or a court, and you can re-run old content when a policy changes. Reviewer decisions become labels, but reviewers also make mistakes, so QA staff re-review a sample, golden items with known answers are mixed into queues to measure each reviewer's accuracy, and disagreement rates per policy show where the policy text itself is unclear. Reviewer wellbeing is a system requirement: blur and greyscale by default, limits on exposure to graphic queues.

8 Trade-offs

Pre-publish blocking vs post-publish removal

Checking everything deeply before publishing gives the best safety but adds minutes of delay that creators hate. Publishing instantly risks spreading harm. The middle path: a fast sync gate for clear violations, instant limited reach, and wide distribution only after async checks.

Specialised classifiers vs one LLM

Classifiers are cheap, fast and calibrated but need labelled data per policy and retraining for new policies. LLMs read policy text and adapt quickly, handle context and sarcasm better, but cost far more per item, are slower and less consistent. Use classifiers for volume and LLMs for the uncertain band and new policies, and distil LLM labels back into classifiers.

Automation vs human review

More automation lowers cost and speeds action, but errors at scale damage trust and may be legally risky for political speech. Keep humans for high-severity, high-reach, low-confidence and appeal cases; measure automation precision continuously before widening it.

9 Bottlenecks

Review queues during a crisis

A riot or a major match can multiply reports 10×. Priority by severity × reach keeps the important items moving; temporarily tighten auto-thresholds for the affected topic (with logging), add surge reviewers, and auto-dedupe near-identical content so one decision applies to thousands of copies via hash clustering.

Video processing cost

At 10× video volume, frame analysis dominates GPU spend. Sample frames adaptively (scene changes, not every second), skip deep analysis for trusted creators with low reach, and run audio and frame models only after a cheap first pass.

10 Failure handling

Sync gate times out or is down

Fail to the safe intermediate state: content is published to the author only ('processing') and released when checks complete. Known-bad hash matching is a separate, very simple service with its own replicas so it is never skipped.

A bad model release over-removes

Shadow-run new models on live traffic first and compare decisions; roll out per policy and language with automatic rollback if removal rate or appeal-overturn rate jumps. Because decisions are logged with model versions, wrongly removed content can be found and restored in bulk.

LLM judge provider outage

Borderline items fall back to the human queue and limited-reach state; no item becomes widely distributed without the check it needs. Queue SLAs and surge staffing absorb the gap.

11 What impresses

  • Separates publishing from distribution, removing the fast-vs-safe dilemma
  • Sets thresholds per policy and per language with a cost argument
  • Sizes the human review team and designs the queue priority formula
  • Uses LLMs where they add value (borderline, new policies) and distils their labels into cheap models
  • Plans for adversarial behaviour, including report brigading
  • Builds auditability and appeals in from the start

12 Mistakes

  • One model, one threshold, for every policy and language
  • Sending all content to an LLM
  • Measuring only precision (from removals) and never estimating recall
  • Ignoring text inside images and speech in videos
  • No appeal path or decision log
  • Treating user reports as ground truth, enabling mass-report abuse

13 Follow-ups

Q1How would you moderate live streams with sub-minute response?
Q2How do you handle AI-generated deepfakes of real people?
Q3How would you evaluate a new classifier for Tamil before launch?
Q4A government order requires removing a post within hours. Walk through the flow.
Q5How do you stop the same banned video being re-uploaded with small edits?
Q6How would you measure whether moderation is making the platform safer overall?

Saved on this device. Create a free account to keep it on every device.

Practise this with Sam

A real mock interview, out loud, with an honest scorecard. Free to start.

Start free