Designing a Counterfeit & Prohibited Listing Detection System at Scale
How marketplaces like Amazon, eBay, Etsy and Flipkart automatically catch fake, stolen, and banned products among millions of new listings every single day — and how to build that system yourself, from first principles.
Introduction and History
Imagine a giant shopping mall that never closes, where anyone in the world can open a new shop in about five minutes. That is what an online marketplace is. Sellers do not need to ask anyone’s permission before putting a product on a shelf — they just upload a photo, write a title, set a price, and the listing goes live almost instantly. This is wonderful for honest sellers, but it also means that a scammer can list a fake “Rolex” watch, a banned pesticide, or a stolen phone just as easily as a legitimate seller lists a genuine product.
A counterfeit and prohibited listing detection system is the invisible security guard of this mall. It watches every new listing, every edited listing, and every re-uploaded photo, and decides — usually within seconds — whether that listing is safe to show to shoppers, needs a human to double check it, or must be taken down (delisted) immediately.
1.1 What do we mean by “counterfeit” and “prohibited”?
These are two different problems that are often solved together because the detection techniques overlap heavily.
Counterfeit products
Fake versions of branded goods — a “Nike” shoe that was never made by Nike, a “Pixel” phone box with a cheap Android inside, or a “Gucci” bag stitched in an unauthorized factory. The seller is trying to trick the buyer into thinking it is the real, trademarked item.
Prohibited products
Items that are illegal or against marketplace policy to sell at all, regardless of authenticity — firearms parts, certain medicines without a license, endangered-species products, hazardous chemicals, or items under a government recall.
1.2 A short history of the problem
eBay and the first “report a listing” button
Early marketplaces relied almost entirely on other users reporting bad listings. Detection was manual and reactive — by the time a fake watch was reported, thousands of buyers may have already seen it.
Keyword blocklists
Marketplaces started maintaining simple lists of banned words (“replica”, “AAA quality”, “1:1 mirror”). This caught the laziest fraudsters but was trivially bypassed by misspellings like “repl1ca” or using Unicode look-alike characters.
Rules engines and image hashing
As catalogs grew into the tens of millions, companies like Amazon and Alibaba built dedicated “Brand Registry” and rights-holder programs, combined with perceptual image hashing to catch reused stolen product photos.
Machine learning enters the pipeline
Deep learning models for image classification (spotting fake logos) and NLP models for text classification became mainstream, letting marketplaces score listings by “counterfeit probability” rather than exact-match rules alone.
Multi-modal, graph-based, real-time detection
Modern systems combine image embeddings, text embeddings, seller network graphs (who is connected to whom), and behavioral signals (how fast a seller lists, price anomalies) into a single real-time risk score, often scanning a listing before it is even published.
By the end of this tutorial you will understand how to design such a system end to end — from the moment a seller clicks “Publish” to the moment a listing is either shown to millions of shoppers or silently removed before anyone ever sees it.
1.3 Why this problem sits at the intersection of several disciplines
Unlike a typical CRUD system, designing this pipeline pulls in ideas from at least four different engineering disciplines at once, and a good system designer needs to be conversant in all of them, even if they are not a specialist in any single one.
Distributed systems
The pipeline must process an unbounded, continuous stream of events reliably, at scale, across multiple data centers, without losing or duplicating decisions.
Machine learning
The system needs models that generalize beyond exact-match rules, continuously retrained as the underlying data distribution shifts.
Trust & safety policy
Legal and policy teams define what counts as a violation in each jurisdiction, and engineering must translate ever-changing policy into executable rules and thresholds.
Human-computer interaction
The reviewer console must let a person make a correct, fast decision on an ambiguous case using the least amount of cognitive load possible, because reviewer throughput directly limits system capacity.
Keeping this multi-disciplinary framing in mind will help you answer follow-up interview questions gracefully, since interviewers often probe from one of these four angles depending on their own background. A candidate who can fluently move between “how would Kafka handle this” and “how would a policy team define this rule” and “how would a reviewer actually use this screen” demonstrates the kind of well-rounded judgment that senior system design interviews are specifically designed to surface.
Problem and Motivation
Why can’t a marketplace just have a human look at every listing before it goes live? Let’s do the maths, because the numbers explain every architectural decision that follows.
8M
New/edited listings per day on a large marketplace.
~93
Listings created every second on average.
300+
Peak listings per second during flash sales.
Thousands
Human reviewers needed if this were done manually.
If a human reviewer can carefully check one listing every 45 seconds, and the marketplace gets 8 million listings a day, the platform would need roughly 4,200 reviewers working around the clock, every single day, forever — and that number only grows as the business grows. This is simply not affordable, and it does not scale with seasonal spikes like festive sales, where listing volume can jump five to ten times overnight.
The system must be fast enough not to slow down honest sellers publishing legitimate products, yet strict enough to catch bad actors who are actively trying to evade detection — and it must do this at a cost of a few fractions of a cent per listing, not dollars.
2.1 Why this is a genuinely hard system design problem
Scale
Millions of listings a day, each producing dozens of signals (text, images, price, seller history) that must all be processed within seconds.
Adversarial actors
Unlike a typical data pipeline, the “input” is actively trying to fool your system. Bad sellers watch what gets caught and adapt — misspelling banned words, using slightly altered images, rotating seller accounts.
Asymmetric cost of errors
A false positive (delisting a genuine seller’s product) damages trust and revenue. A false negative (letting a counterfeit through) damages buyer trust and can trigger legal liability. Both must be minimized simultaneously.
Multi-modal data
Signals come from text, images, seller metadata, pricing, and even video — each needing different processing pipelines that must be fused into one decision.
Global & multi-jurisdiction
A product prohibited in the EU (like certain chemicals) may be legal in another country. Rules must be regionalized, not one-size-fits-all.
Explainability
When you delist a seller’s product, you may legally be required to explain why — “black box” ML decisions alone are not enough; you need an audit trail.
The goal is not to build a system that is 100% accurate — that is impossible. The goal is to build a system that keeps getting better than the adversary, faster than the adversary can adapt.
“Why can’t you just use a keyword blocklist for prohibited items?” A good answer covers: blocklists are trivially evaded through misspellings, Unicode homoglyphs (using a Cyrillic “а” instead of Latin “a”), and synonym substitution; they produce no confidence score, so you cannot triage by risk; and they cannot detect visual counterfeits at all, since the violation may be entirely in an image, not the text.
2.2 The three stakeholders whose needs must all be balanced
A well-designed system is ultimately a balancing act between three groups of people, each with legitimate but sometimes conflicting needs. Losing sight of any one of them tends to produce a system that looks good on paper but fails in practice.
| Stakeholder | What they need | What happens if ignored |
|---|---|---|
| Honest sellers | Fast publishing, clear reasons for any rejection, a fair appeals path | Sellers churn to competitor marketplaces; marketplace loses supply-side liquidity |
| Buyers | Confidence that products are genuine, safe, and legally sellable | Buyers lose trust, return rates spike, and the marketplace brand suffers long-term damage |
| Regulators & brand owners | Demonstrable due diligence, an auditable enforcement process, rapid takedown of reported infringement | Legal liability, fines, and in extreme cases loss of the right to operate in certain markets |
2.3 The economics of the arms race
It helps to think about this problem the way a security team thinks about fraud: as an ongoing economic contest rather than a puzzle with a final answer. Every improvement you make to detection raises the cost of running a counterfeit operation on your platform — a counterfeiter now needs a fresh seller account, a new product photo, and slightly reworded text just to get past your system once. If your defenses are strong and adaptive, the cost of evasion eventually exceeds the profit a counterfeiter can extract, and they move to an easier target. If your defenses are static, the opposite happens: the cost of evasion trends toward zero over time as bad actors reverse-engineer your rules, and your platform becomes a magnet for exactly the sellers you do not want.
This economic framing also explains why pure accuracy metrics on a fixed historical test set can be misleading. A model that scores 98% accuracy on last year’s counterfeit examples may perform far worse against this month’s evasion tactics, because the underlying “test set” — the population of bad actors and their behavior — is not static. It is actively responding to your defenses.
Core Concepts
Before we draw any boxes and arrows, let’s build a shared vocabulary. Every term below will reappear throughout the architecture section, so take your time here.
3.1 Perceptual hashing (pHash)
What: A technique that converts an image into a short fingerprint (a string of bits) such that visually similar images produce similar fingerprints, even if one image is resized, slightly cropped, or has a watermark added.
Why: Counterfeiters frequently steal a genuine seller’s product photo and reuse it. A perceptual hash lets you detect “this image is 96% similar to a photo already used by a verified brand” in microseconds, without running an expensive deep learning model.
Analogy: Think of it like a fingerprint at a crime scene. Two fingers can never be pixel-identical, but a forensic expert can tell they belong to the same person by comparing the pattern of ridges, not every microscopic detail.
Practical example: Amazon’s rights-holder program lets brand owners upload “golden” reference images of their real products. Every new listing photo is hashed and compared against this reference set within a vector database.
3.2 Embeddings and vector search
What: An embedding is a list of numbers (a vector), typically a few hundred to a few thousand values long, produced by a neural network, that represents the “meaning” of a piece of text or an image. Similar items end up with vectors that are mathematically close to each other.
Why: Unlike exact keyword matching, embeddings let you find items that are semantically similar even if the wording or pixels are completely different — for example, “replica,” “inspired by,” and “1:1 mirror quality” all cluster near each other in text-embedding space, even though they share no common substring.
Beginner example: Imagine every product description gets converted into a point on a giant map. “Genuine leather wallet” and “real leather wallet” land right next to each other on this map, while “genuine leather wallet” and “wireless mouse” land far apart.
Production example: A nearest-neighbor search in a vector database (like a specialized ANN index) can answer, “show me the 20 most similar listings to this one,” in single-digit milliseconds even across a catalog of hundreds of millions of items.
3.3 Rules engine
What: A deterministic system that evaluates explicit, human-written policies — for example, “IF category = electronics AND brand = Apple AND price < 15% of MSRP THEN flag as high risk.”
Why: Rules are instantly explainable (crucial for legal and appeals processes), fast to update (a policy team can push a new rule in minutes without retraining a model), and excellent at catching known, well-understood patterns.
Trade-off: Rules alone cannot generalize to novel evasion tactics; that’s what ML scoring is for.
3.4 ML classifier / scoring model
What: A machine learning model — often an ensemble of gradient-boosted trees for tabular signals plus a deep neural network for text/image embeddings — that outputs a single probability, e.g., “87% likely counterfeit.”
Why: Learns subtle, non-obvious patterns from millions of historical labeled examples (things reviewers previously confirmed as counterfeit or genuine) that a human could never encode as explicit rules.
3.5 Confidence thresholding & the review queue
What: Instead of treating every decision as a strict yes/no, the system defines score bands: below a low threshold, the listing is approved automatically; above a high threshold, it is auto-delisted; anything in between goes to a human reviewer.
Analogy: Think of airport security. Most passengers walk straight through (low risk). A very small number are obviously flagged and pulled aside immediately (high risk). Everyone else in between gets a quick secondary screening by a human.
3.6 Seller risk / reputation graph
What: A graph where nodes are sellers, buyers, devices, bank accounts, and addresses, and edges represent shared attributes. Fraud rings often reuse the same bank account or shipping address across “different” seller identities.
Why: A single listing in isolation may look fine, but if the seller account is three days old, linked by IP address to five previously banned accounts, and listing luxury goods at 20% of retail price, the graph reveals the pattern instantly.
3.7 Model calibration
What: Calibration means that when a model outputs “80% probability of counterfeit,” that number should genuinely correspond to roughly 80 out of 100 similar cases actually being counterfeit — not just a relative ranking score that happens to use the 0–1 scale.
Why: The entire confidence-thresholding design depends on scores meaning what they claim to mean. An uncalibrated model might rank items correctly relative to each other while its absolute numbers are wildly off, which would silently break your carefully-tuned auto-approve and auto-delist thresholds.
Practical example: Teams typically apply a calibration step (such as Platt scaling or isotonic regression) on top of the raw model output, validated against a held-out set of confirmed reviewer decisions, before the score is ever used to drive an automatic action.
3.8 Active learning
What: A training strategy where the model itself helps decide which new examples are most valuable for a human to label next, rather than labeling data at random.
Why: Human review time is the scarcest resource in the entire system. Active learning prioritizes sending the model’s most uncertain, most informative cases to reviewers, so every hour of human review time contributes the maximum possible improvement to the next model version.
Analogy: A good teacher does not ask a struggling student to re-practice problems they already know how to solve; they focus on the specific gaps in the student’s understanding. Active learning applies the same idea to model training.
No single signal — not the image, not the text, not the seller’s history — is sufficient on its own. The entire architecture exists to combine many weak, individually-fallible signals into one strong, well-calibrated decision.
Architecture and Components
Now let’s put all of these concepts into one coherent picture. The diagram below shows every major component, labeled explicitly, from the moment a request enters the system to the moment a decision is made.
Every box above is a real, independently deployable service. Let’s walk through each one and explain what an interviewer would expect you to know about it.
4.1 Component breakdown
Load Balancer
Sits directly behind the CDN and in front of the API Gateway fleet. Distributes incoming HTTP traffic across many gateway instances using round robin or least-connections, and performs health checks so traffic never reaches a dead instance.
API Gateway
The single front door for all client requests. Handles authentication (is this a real seller session?), authorization (can this seller edit this listing?), rate limiting (stop one seller from flooding the system with 10,000 listings a minute), and routes requests to the correct downstream service.
Listing Service
Owns the “create” and “update” business logic for listings. Writes the initial record with a status of PENDING_REVIEW and immediately publishes an event — it does not wait for the detection pipeline synchronously, keeping the seller-facing API fast.
Event Bus (Kafka)
Decouples the fast-write path (Listing Service) from the slower, heavier detection pipeline. Guarantees at-least-once delivery and lets you replay events if a downstream consumer crashes or a model needs re-scoring historical data.
Feature Extraction Service
The orchestrator that fans out to image hashing, NLP, and seller-risk services in parallel, then assembles one unified feature vector per listing.
Image Hashing / Embedding Service
Generates perceptual hashes for exact/near-duplicate detection and deep embeddings for semantic visual similarity (e.g., detecting a fake logo even on a never-before-seen photo).
NLP Service
Tokenizes and classifies title/description text, detects banned keywords (with fuzzy matching for evasion attempts), and generates text embeddings for semantic search.
Seller Risk Service
Computes a real-time reputation score using account age, past violation count, shared-identity graph signals, and behavioral anomalies like sudden listing bursts.
Vector Database
Stores millions of reference embeddings (from verified brand images and known counterfeit examples) and supports approximate nearest-neighbor queries in milliseconds.
Rules Engine
Evaluates deterministic, human-authored policies. Fast, explainable, and instantly updatable without a model retrain — the first line of defense for known, well-understood violation patterns.
ML Scoring Service
Combines rule flags, embeddings, and risk scores into one calibrated probability using an ensemble model, typically served behind a low-latency inference API.
Decision Service
Applies confidence thresholds to the ML score and routes the listing to one of three outcomes: auto-approve, auto-delist, or human review.
Human Review Queue & Reviewer Console
A priority queue (highest-risk / highest-traffic listings reviewed first) feeding a case-management UI where trained reviewers make the final call on ambiguous cases.
Cache Layer (Redis)
Caches hot listing reads so the Search Service does not hit the primary Catalog Database for every single shopper page view.
Notification Service
Informs sellers of decisions and appeal rights, and can notify internal legal/compliance teams for high-severity prohibited-item cases (e.g., weapons).
“Why is there both a Rules Engine and an ML Scoring Service — isn’t that redundant?” Strong answer: they solve different problems. The rules engine gives instant, explainable, zero-training-time coverage for known bad patterns (a banned brand name, a known-fake SKU). The ML model generalizes to new, previously unseen evasion patterns that no one has written a rule for yet. In production, rule hits are often also fed as one of the input features into the ML model itself, so the ML layer can learn how much to trust each rule over time.
Internal Working
Let’s zoom into how the Feature Extraction and ML Scoring stages actually work internally, since this is where interviewers dig the deepest.
5.1 Step 1: Normalization
Raw listing text is lower-cased, stripped of excessive whitespace, and Unicode-normalized (NFKC normalization) so that visually identical characters from different alphabets — a common evasion trick — are collapsed into one canonical form before any matching happens. This single step quietly defeats a large fraction of naive evasion attempts, because it removes the “surface-level noise” that a sneaky seller relies on to slip past exact-match systems, without needing any machine learning at all.
5.2 Concurrency inside the Feature Extraction Service
A single listing’s feature extraction fans out to three independent downstream calls — image hashing, NLP, and seller risk — that do not depend on each other’s output. Running these sequentially would triple the latency for no benefit, so the service issues all three calls concurrently and joins the results once every call completes or times out. In Java, this is naturally expressed using CompletableFuture, where each downstream call runs on its own thread from a bounded pool (a bulkhead, so a slow image-hashing call cannot starve threads needed for NLP), and the three futures are combined once all are done:
public class FeatureExtractionOrchestrator {
private final ExecutorService imageExecutor;
private final ExecutorService nlpExecutor;
private final ExecutorService riskExecutor;
public FeatureBundle extract(NormalizedListing listing) throws ExtractionException {
CompletableFuture<ImageFeatures> imageFuture =
CompletableFuture.supplyAsync(() -> imageHashClient.extract(listing), imageExecutor)
.orTimeout(200, TimeUnit.MILLISECONDS)
.exceptionally(ex -> ImageFeatures.empty());
CompletableFuture<TextFeatures> textFuture =
CompletableFuture.supplyAsync(() -> nlpClient.extract(listing), nlpExecutor)
.orTimeout(150, TimeUnit.MILLISECONDS)
.exceptionally(ex -> TextFeatures.empty());
CompletableFuture<RiskFeatures> riskFuture =
CompletableFuture.supplyAsync(() -> riskClient.extract(listing), riskExecutor)
.orTimeout(100, TimeUnit.MILLISECONDS)
.exceptionally(ex -> RiskFeatures.empty());
return CompletableFuture.allOf(imageFuture, textFuture, riskFuture)
.thenApply(ignored -> FeatureBundle.combine(
imageFuture.join(), textFuture.join(), riskFuture.join()))
.join();
}
}Notice that each future has its own fallback (exceptionally) returning an empty feature set rather than propagating the exception. This design choice means a single slow or failing downstream dependency degrades the quality of the final feature bundle slightly, rather than failing the entire extraction for that listing — a direct application of the bulkhead and graceful-degradation patterns discussed later in this tutorial.
5.3 Step 2: Multi-modal feature extraction
| Signal type | Extraction technique | Example output |
|---|---|---|
| Text | Tokenization + transformer-based text embedding model | 768-dimension vector representing listing title/description meaning |
| Image | Perceptual hash (pHash/aHash) + CNN embedding | 64-bit hash + 512-dimension visual embedding |
| Price | Z-score against category median MSRP | -2.4 (price is 2.4 standard deviations below normal) |
| Seller | Graph features + account metadata | account_age_days=3, shared_bank_accounts=4, prior_violations=2 |
| Behavioral | Time-series anomaly detection | listing_burst_score=0.91 (91st percentile burst rate) |
5.4 Step 3: Rule evaluation
The rules engine runs a decision-table style evaluation. Each rule produces a boolean flag plus a severity weight. A simple example in Java, representing one rule inside a larger rule-chain:
public class ProhibitedKeywordRule implements ListingRule {
private final FuzzyMatcher matcher;
private final Set<String> prohibitedTerms;
public ProhibitedKeywordRule(Set<String> prohibitedTerms, double fuzzyThreshold) {
this.prohibitedTerms = prohibitedTerms;
this.matcher = new FuzzyMatcher(fuzzyThreshold);
}
@Override
public RuleResult evaluate(NormalizedListing listing) {
String text = listing.getNormalizedTitle() + " " + listing.getNormalizedDescription();
for (String term : prohibitedTerms) {
if (matcher.matchesFuzzy(text, term)) {
return RuleResult.builder()
.ruleName("PROHIBITED_KEYWORD")
.matched(true)
.severity(Severity.HIGH)
.evidence("Matched term near: " + term)
.build();
}
}
return RuleResult.notMatched("PROHIBITED_KEYWORD");
}
}5.5 Step 4: ML ensemble scoring
The ML Scoring Service typically combines a gradient-boosted tree model (great for tabular seller/price/rule-flag features) with a fusion layer that also takes the text and image embeddings as inputs. A simplified client call to this internal inference service:
public class MlScoringClient {
private final HttpClient httpClient;
private final String inferenceEndpoint;
private final CircuitBreaker circuitBreaker;
public ScoreResponse scoreListing(FeatureBundle features) throws ScoringException {
if (circuitBreaker.isOpen()) {
// Fail safe: fall back to rules-only decision when the model is unavailable
return ScoreResponse.fallback(features.getRuleAggregateScore());
}
try {
String requestBody = JsonMapper.toJson(features);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(inferenceEndpoint))
.timeout(Duration.ofMillis(150))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
circuitBreaker.recordSuccess();
return JsonMapper.fromJson(response.body(), ScoreResponse.class);
} catch (Exception e) {
circuitBreaker.recordFailure();
throw new ScoringException("ML scoring call failed", e);
}
}
}Notice the 150 millisecond timeout above. In a real-time pipeline serving hundreds of listings per second, the ML inference call must have an aggressive timeout and a circuit breaker so that one slow model server never cascades into a full pipeline stall. A rules-only fallback score is always better than blocking the entire ingestion pipeline.
5.6 Step 5: Decision aggregation
The Decision Service combines the rule severity, ML probability, and seller risk score into one final action using a weighted formula, then compares it against configurable thresholds — for example, score > 0.9 triggers auto-delist, 0.4–0.9 goes to human review, and below 0.4 is auto-approved.
“What happens if the ML model is down — should the pipeline block?” No. This is a classic graceful-degradation question. The correct answer is a circuit breaker pattern: after a threshold of failures, stop calling the model, fall back to a conservative rules-only score (perhaps routing more listings to human review than usual), and keep the seller-facing publish flow unaffected. Blocking listing creation because a downstream ML service is unhealthy would be a severe availability regression for a non-critical-path dependency.
Data Flow and Lifecycle
Let’s trace one single listing from creation to final decision as a sequence of messages between services.
6.1 Listing lifecycle states
Every listing moves through a well-defined state machine. Modeling this explicitly avoids ambiguous states like “half-approved” that are hard to reason about later.
| State | Meaning | Visible to shoppers? |
|---|---|---|
| DRAFT | Seller is still editing, not yet submitted | No |
| PENDING_REVIEW | Submitted, awaiting detection pipeline result | No (or soft-published depending on business rules) |
| APPROVED | Passed automated checks, live on the marketplace | Yes |
| UNDER_HUMAN_REVIEW | Ambiguous score, awaiting reviewer decision | Depends on policy — often hidden until cleared |
| DELISTED | Confirmed violation, removed from catalog | No |
| APPEALED | Seller disputed a delist decision, under re-review | No |
Many marketplaces choose to make low-risk-category listings visible immediately (optimistic publish) while the pipeline runs asynchronously in the background, only pulling the listing down retroactively if a violation is later confirmed. This keeps the seller experience fast. High-risk categories (electronics, luxury goods, pharmaceuticals) are often held in PENDING_REVIEW until cleared, trading a few seconds of seller-visible delay for stronger buyer protection.
Advantages, Disadvantages and Trade-offs
Advantages of this architecture
- Decoupled, event-driven pipeline scales each stage independently — you can add more NLP workers without touching image hashing.
- Layered defense (rules + ML + human review) balances speed, coverage, and explainability.
- Asynchronous processing keeps the seller-facing publish API fast regardless of how heavy the detection pipeline is.
- Confidence thresholding focuses expensive human attention only where it is genuinely needed.
Disadvantages & challenges
- Significant operational complexity — many moving services, each with its own failure modes.
- Eventual consistency between “listing created” and “listing scanned” creates a short window where a bad listing could theoretically be seen by a shopper.
- ML models require constant retraining as adversaries adapt (concept drift), adding ongoing MLOps cost.
- Human review queues can become a bottleneck during traffic spikes if not carefully capacity-planned.
7.1 Key trade-off: synchronous vs asynchronous scanning
| Approach | Pros | Cons |
|---|---|---|
| Synchronous (block publish until scanned) | Zero window of exposure; no bad listing is ever shown, even briefly | Adds latency to every seller’s publish flow; harder to scale during spikes |
| Asynchronous (publish, scan in background) | Fast seller experience; pipeline can be scaled and buffered independently | Small exposure window; requires a robust retroactive takedown mechanism |
| Hybrid (sync for high-risk categories only) | Best of both — speed for low-risk, safety for high-risk | More complex routing logic and category-risk classification to maintain |
7.2 Key trade-off: precision vs recall
Raising the auto-delist threshold increases precision (fewer genuine sellers wrongly delisted) but lowers recall (more real counterfeits slip through as “ambiguous” and pile up in the review queue, or worse, get auto-approved). Lowering the threshold does the opposite. Most marketplaces tune this per-category — luxury goods might tolerate more false positives (send more borderline cases to review) since counterfeit risk and brand damage are higher there.
Performance and Scalability
At 300+ listings per second during peak sales events, every stage of the pipeline must be individually horizontally scalable.
8.1 Horizontal scaling of the feature extraction layer
Because feature extraction is stateless (it just transforms an event into a feature bundle), you can scale the ingestion worker pool horizontally simply by adding more consumer instances to the Kafka consumer group — Kafka automatically rebalances partitions across them.
8.2 Batching for the ML scoring service
GPU-backed inference is far more cost-efficient when requests are batched. A common pattern is a small (10–30 millisecond) micro-batching window at the inference server that groups incoming requests, trading a tiny bit of added latency for dramatically higher throughput per GPU.
8.3 Sharding the vector database
With hundreds of millions of reference embeddings, a single vector index cannot fit in memory on one machine. The index is sharded by category (electronics, apparel, etc.) so a query only needs to search the relevant shard, cutting both memory footprint and query latency.
8.4 Little’s Law applied to the review queue
Little’s Law states L = λW, where L is the average number of items in the system, λ is the arrival rate, and W is the average time an item spends in the system. If listings needing human review arrive at 20 per second (λ) and each review takes an average of 90 seconds (W), the review queue will stabilize at L = 20 × 90 = 1,800 listings in flight at any given moment — which directly tells you how many concurrent reviewer seats you need to keep the queue from growing unbounded.
If a flash sale doubles listing volume, and thus doubles the ambiguous-score rate, you need double the reviewer capacity (or a tighter threshold to shrink the ambiguous band) — otherwise queue wait time W grows unboundedly per Little’s Law, and listings sit unreviewed for hours.
8.5 Caching strategy
Approved, live listings are cached aggressively (read-heavy workload — shoppers view a listing far more often than sellers edit it). A cache-aside pattern with a short TTL plus explicit invalidation on delist events ensures a delisted item disappears from shopper view within seconds, not minutes.
“How would you scale the vector similarity search if the reference image dataset grows to a billion images?” Discuss approximate nearest neighbor (ANN) indexes such as HNSW or IVF-based indexes that trade a small amount of recall for massive speed gains over exact search, combined with sharding by category and pre-filtering by coarse metadata (brand, category) before the expensive vector comparison, so each query only searches a small relevant subset of the index.
8.6 CAP theorem trade-offs in this system
The CAP theorem states that a distributed data store can only guarantee two of three properties during a network partition: consistency, availability, and partition tolerance. This pipeline deliberately makes different choices for different pieces of state, and being able to articulate why is a strong signal in an interview.
| Component | Choice | Reasoning |
|---|---|---|
| Catalog Database (listing status) | Favors consistency (CP) | Two conflicting writes to the same listing’s status must never both “win” silently; a stale read showing a delisted item as live is a real trust and safety failure. |
| Event Bus (Kafka) | Favors availability (AP) with at-least-once delivery | It is safer to occasionally reprocess a duplicate event (handled via idempotency) than to lose an event entirely or block ingestion during a partition. |
| Cache layer (Redis) | Favors availability (AP) | A shopper briefly seeing a stale cached listing is a minor inconvenience, not a safety failure, so cache reads remain available even during replication lag. |
| Vector Database (reference embeddings) | Favors availability (AP) with eventual consistency | A newly added reference image being searchable a few seconds late is an acceptable trade-off for keeping similarity search highly available under load. |
This table illustrates an important general principle for system design interviews: CAP trade-offs are not made once for the “whole system,” but individually for each piece of state, based on the actual cost of inconsistency versus the actual cost of unavailability for that specific piece of data.
High Availability and Reliability
9.1 Multi-AZ / multi-region deployment
Every stateful component — the Kafka cluster, the Catalog Database, the Vector Database — is deployed across at least three availability zones, so the loss of a single data center does not interrupt listing creation or detection.
9.2 Graceful degradation chain
ML service down
Circuit breaker trips; fall back to rules-only score; route more listings to human review as a safety margin.
Vector DB unavailable
Skip image-similarity signal for this scoring pass; rely on text and rule signals; flag the listing for a follow-up re-scan once the vector DB recovers.
Review queue overloaded
Auto-escalate only the highest-risk cases to a smaller “fast lane” of senior reviewers; temporarily tighten auto-approve threshold to reduce inflow.
Event bus consumer lag
Alerts fire on consumer lag exceeding an SLA (e.g., 60 seconds); auto-scaling adds more consumer instances to the group.
9.3 Disaster recovery
The Catalog Database and Case Management Database (which holds the audit trail — legally important for appeals and regulatory requests) are backed up continuously with point-in-time recovery, and Kafka topics retain enough history (e.g., 7 days) to allow full pipeline replay if a bug is discovered in the ML scoring logic and past decisions need to be recomputed.
Because Kafka guarantees at-least-once delivery, the same listing-created event could be processed twice during a consumer rebalance. Every downstream write (feature extraction, decision recording) must be idempotent — keyed by a unique listing-version id — so reprocessing never double-delists or double-notifies a seller.
“How do you guarantee a delist decision is never lost, even if the Decision Service crashes mid-processing?” Good answer: the decision is written to the Case Management Database (durable, replicated storage) inside the same logical transaction as the Kafka consumer offset commit, using an outbox pattern or transactional messaging, so a crash before the write completes means the event is reprocessed from the last committed offset rather than silently dropped.
9.4 Consensus and leader election for queue partition assignment
The priority review queue is itself a partitioned, replicated system, since a single queue instance cannot durably hold hundreds of thousands of in-flight cases while staying highly available. Partition ownership (which broker owns which slice of the queue) is coordinated using a consensus protocol under the hood of the underlying messaging platform, ensuring that exactly one node is ever the active leader for a given partition at a time. If that leader node fails, the remaining replicas run a leader election to promote a new one, using the same class of algorithm (such as Raft) that underlies many modern coordination services. The practical consequence for the application layer is simple even though the underlying mechanism is subtle: consumers should always assume partition ownership can change at any moment, and must be written to rejoin the correct partition and resume from the last committed offset without manual intervention.
9.5 Failure recovery drills
Reliability on paper is not the same as reliability in practice. Mature teams run scheduled game days where they deliberately kill a Catalog Database replica, inject artificial latency into the ML Scoring Service, or partition the Kafka cluster, and verify that the system degrades exactly the way the design predicts — falling back to rules-only scoring, routing more listings to review, and recovering automatically once the fault is resolved, all without a human needing to intervene at 3 a.m.
Security
10.1 Protecting the detection system itself from adversaries
Unlike most systems, here the “attacker” is trying to fool your business logic, not just breach your infrastructure. Both angles matter.
Model evasion defense
Rate-limit how often a single seller can re-submit a slightly modified listing, since repeated near-identical submissions with tiny tweaks is a classic signal of someone probing the model for its blind spots.
Reference data integrity
Brand-owner-submitted “golden” reference images must go through their own verification pipeline — otherwise a bad actor could poison the reference set itself by falsely claiming a fake image is the genuine brand photo.
Reviewer access control
Strict role-based access control on the Reviewer Console; every decision is logged with the reviewer’s identity for audit purposes, and reviewer accounts get anomaly monitoring (is one reviewer approving suspiciously fast, or always approving one seller’s items?).
API security
Standard measures apply at the gateway layer: mutual TLS between internal services, OAuth2/JWT-based auth for seller sessions, strict input validation to prevent injection through listing text fields, and WAF rules against common web attack patterns.
10.2 Data privacy
Seller identity documents, bank account details used for risk graphing, and buyer complaint data are highly sensitive. These are encrypted at rest and in transit, access is scoped tightly (principle of least privilege), and retention policies comply with applicable data protection regulations for each operating region.
10.3 Least privilege for internal service-to-service access
Each internal service is issued its own narrowly scoped credential rather than a shared master credential, so that a compromise of, say, the NLP Service cannot be used to directly query the Seller Risk Service’s underlying bank-account graph data. Service identities are managed through short-lived certificates rotated automatically, and every cross-service call is logged with the calling service’s identity, making lateral movement inside the pipeline both harder to achieve and far easier to detect after the fact.
10.4 Symmetric encryption and password hashing for stored credentials
Where the system stores sensitive configuration such as third-party rights-holder API keys, it uses strong symmetric encryption (for example AES-256) with keys held in a dedicated secrets-management service rather than embedded in application configuration. Reviewer console passwords, similarly, are never stored directly — only a salted, slow cryptographic hash (such as bcrypt or Argon2) is stored, so that even a full database compromise does not directly expose usable credentials.
“A seller claims their genuine listing was wrongly delisted as counterfeit. How does your system support a fair appeal process?” The Case Management Database’s audit trail is key here: every decision stores which rule fired, the ML score, the model version used, and (if applicable) the human reviewer’s notes. An appeal routes the case to a senior reviewer with full visibility into this trail, and if reversed, the correction is fed back as a labeled training example to improve the model — closing the feedback loop.
Monitoring, Logging and Metrics
11.1 Key metrics to track
| Metric | Why it matters |
|---|---|
| Detection latency (p50/p95/p99) | How long from listing submission to decision; slow tails delay legitimate sellers |
| Auto-approve / auto-delist / review split | Tracks how well-calibrated thresholds are; a sudden shift may indicate model drift |
| Reviewer queue depth & wait time | Directly maps to Little’s Law capacity planning; leading indicator of SLA breach |
| False-positive rate (seller appeals upheld) | Measures harm to genuine sellers; a core trust metric |
| Kafka consumer lag | Detects a stalling or under-scaled ingestion pipeline before it becomes a backlog crisis |
| Model score distribution drift | Alerts if the ML score distribution shifts significantly, hinting at adversarial adaptation or data pipeline bugs |
11.2 Logging & tracing
Every listing carries a correlation id (a trace id) from the moment it is created through every service it touches, enabling distributed tracing across the Feature Extraction, Rules Engine, ML Scoring, and Decision Service. This is essential for debugging: when a seller complains “my listing has been stuck in review for 3 days,” an engineer can look up that one trace id and see exactly which stage it is stuck at.
Alert on symptoms that affect users (rising p99 latency, growing queue depth, spiking false-positive rate) rather than only on low-level infrastructure metrics (CPU usage). A CPU spike that does not affect detection latency or accuracy is not actionable at 3 a.m.
“How would you detect that your ML model’s performance is silently degrading in production?” Discuss monitoring the model’s score distribution over time (population stability index), tracking the rate of reviewer overturns of ML-driven auto-decisions as a proxy for accuracy, and running periodic shadow evaluations where a small percentage of traffic is scored by both the current production model and a challenger model, comparing agreement rates.
Deployment and Cloud Architecture
12.1 Containerized microservices on Kubernetes
Each service (Feature Extraction, Rules Engine, ML Scoring, Decision Service) runs as an independently deployable container, orchestrated by Kubernetes, with horizontal pod autoscaling driven by custom metrics such as Kafka consumer lag rather than CPU alone — since these workloads are often I/O-bound waiting on downstream calls.
12.2 Blue-green and canary rollouts for ML models
A new model version is never rolled out to 100% of traffic instantly. Instead, it is first deployed as a shadow model (scoring traffic silently without affecting decisions), then canaried to a small percentage of real traffic, with automated rollback if the false-positive or false-negative rate regresses beyond an acceptable band.
12.3 Infrastructure as Code
The entire pipeline’s infrastructure — Kafka topics, database schemas, Kubernetes manifests, autoscaling policies — is defined declaratively and version-controlled, so the exact same environment can be reproducibly stood up in a disaster-recovery region.
GPU-backed ML inference is the most expensive part of this pipeline. Techniques to control cost include model distillation (a smaller, faster model for the first-pass score, escalating only genuinely ambiguous cases to a larger, more expensive model), request batching, and auto-scaling inference pods down aggressively during low-traffic hours.
12.4 Comparing rollout strategies for model and rule changes
| Strategy | How it works | Best used for |
|---|---|---|
| Shadow deployment | New model scores live traffic silently; output logged but never acted upon | Validating a brand-new model version before it can affect any real decision |
| Canary rollout | New version handles a small percentage (e.g., 5%) of real traffic, with automated rollback on regression | Gradually building confidence in a validated model before full rollout |
| Blue-green | An entire parallel environment is stood up and traffic is switched over atomically | Large infrastructure or schema changes where a fast, clean rollback is essential |
| Feature-flagged rule change | New rule ships disabled, then enabled for a subset of categories or regions | Fast-moving policy updates that need to ship without a full deployment cycle |
12.5 Multi-region disaster recovery
Beyond multi-AZ resilience within one region, the platform maintains a warm standby deployment of the entire detection pipeline in a secondary geographic region. Database replication keeps this standby’s data within a small, bounded lag of the primary region, and infrastructure-as-code definitions make it possible to promote the standby to primary in minutes rather than hours if an entire region becomes unavailable — a scenario that, while rare, has real historical precedent across major cloud providers and cannot be dismissed for a system with legal and safety obligations.
Databases, Caching and Load Balancing
13.1 Catalog Database choice
A distributed relational or wide-column database is typically used for the Catalog Database, since listing status transitions benefit from strong consistency guarantees (you never want two conflicting writes to leave a listing in an undefined state), while still needing to scale horizontally by sharding on seller id or listing id.
13.2 Case Management Database
Optimized for append-heavy audit-trail writes and complex queries by reviewers (find all pending cases for category X sorted by risk score). A document-oriented store often fits well here since each case’s structure (rule flags, ML scores, reviewer notes) varies in shape.
13.3 Vector Database
A purpose-built vector index supporting approximate nearest-neighbor search, sharded by category, with periodic re-indexing as new reference images are added by verified brand owners.
13.4 Cache layer design
A distributed in-memory cache sits in front of the Catalog Database for read-heavy shopper traffic. Cache invalidation on delist events is push-based (an event triggers immediate cache eviction) rather than relying solely on TTL expiry, since a delisted counterfeit item must disappear from shopper view immediately, not after a stale cache entry expires minutes later.
13.5 Load balancing strategy
Layer 7 load balancing at the edge routes by URL path (listing-creation traffic vs. search-query traffic can go to differently-scaled backend pools). Internally, service-to-service calls use client-side load balancing with health-aware routing so a single slow feature-extraction instance does not receive a disproportionate share of new requests.
13.6 Indexing strategy for the Catalog Database
Reviewer queries (find all pending cases for a given category, sorted by risk score) and shopper queries (find a listing by id, or search within a category) have very different access patterns, so they are supported by different indexes. A composite index on (category, status, risk_score) accelerates the reviewer workflow, while a separate index on (seller_id, status) accelerates a seller’s “my listings” view. Over-indexing is avoided deliberately, since every additional index adds write overhead on the already write-heavy listing-creation path, and index choices are revisited whenever a new dominant query pattern emerges.
13.7 Normalization versus denormalization
The Catalog Database’s core listing table is kept reasonably normalized (separating seller, listing, and category data into related tables) to avoid update anomalies when, for instance, a seller’s display name changes. The Search Service’s read-optimized view, by contrast, is deliberately denormalized — pre-joining listing, seller, and category data into a single flattened document — because shopper-facing search traffic is overwhelmingly read-heavy and benefits far more from avoiding expensive joins at query time than from strict normalization.
APIs and Microservices
14.1 Sample internal API contract
@RestController
@RequestMapping("/internal/v1/decisions")
public class DecisionServiceController {
private final DecisionOrchestrator orchestrator;
@PostMapping("/{listingId}/evaluate")
public ResponseEntity<DecisionResult> evaluate(
@PathVariable String listingId,
@RequestBody FeatureBundle features) {
DecisionResult result = orchestrator.decide(listingId, features);
// Persist an immutable audit record before returning the result
orchestrator.recordAuditTrail(listingId, result);
return ResponseEntity.ok(result);
}
@GetMapping("/{listingId}")
public ResponseEntity<DecisionResult> getDecision(@PathVariable String listingId) {
return orchestrator.findDecision(listingId)
.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
}14.2 Why microservices, not a monolith, for this domain
Each stage of the pipeline (image processing, NLP, rules, ML scoring) has wildly different scaling characteristics and technology needs — image hashing may need GPU bursts during peak uploads, while the rules engine is CPU-light but latency-critical. Splitting these into independently scalable services lets each team own its component’s deployment cadence, and a bug or crash in the NLP service does not take down the Rules Engine.
14.3 Synchronous vs asynchronous API design
The Listing Service’s public API (used by sellers) is synchronous and fast — it only writes the initial record and publishes an event. All internal detection-pipeline services communicate primarily through the event bus (asynchronous), except for the low-latency ML Scoring call, which is a direct synchronous RPC because the Decision Service needs an immediate response within its processing budget.
“Would you use REST, gRPC, or messaging for the Feature Extraction to ML Scoring Service call?” gRPC is usually the strongest choice for this specific internal, low-latency, high-throughput call — its binary protocol and HTTP/2 multiplexing reduce overhead compared to REST/JSON, which matters when you are making hundreds of these calls per second within a tight latency budget. Messaging remains the right choice for the broader event-driven backbone where near-real-time (not sub-100ms) delivery is acceptable.
Design Patterns and Anti-Patterns
15.1 Patterns used in this design
Circuit Breaker
Used around the ML Scoring call to prevent a slow or failing model server from cascading into a full pipeline stall; falls back to a rules-only score.
Outbox Pattern
Ensures decision writes to the Case Management Database and the corresponding Kafka event publish happen atomically, avoiding “decision made but never notified” bugs.
Strangler Fig
Used historically when migrating from a legacy keyword-blocklist system to the modern ML pipeline — new traffic is gradually routed to the new system category by category, rather than a risky big-bang cutover.
CQRS (Command Query Responsibility Segregation)
Listing writes go through the Listing Service; listing reads for shoppers go through a separately optimized, cache-heavy Search Service read path — the two are deliberately not the same code path.
Saga Pattern
Coordinates the multi-step “delist” workflow (update catalog status, invalidate cache, notify seller, log audit trail) with compensating actions if any step fails partway through.
Bulkhead
Isolates thread pools per downstream dependency (image hashing, NLP, seller risk) so a slow image-hashing service cannot starve the thread pool needed for NLP calls.
15.2 Anti-patterns to avoid
Single monolithic “god” rule
One giant if-else block encoding every policy, impossible to test or reason about; instead, use a composable rule-chain.
Blocking synchronous scanning everywhere
Unnecessarily slows down low-risk sellers; use risk-based routing instead so only high-risk categories block the publish flow.
No feedback loop from reviewers to model training
The ML model goes stale and never learns from confirmed reviewer corrections, letting model quality quietly decay over time.
Treating the review queue as infinite
Without proper capacity planning per Little’s Law, queue wait times silently balloon during traffic spikes and reviewer SLAs quietly break.
Hard-coding thresholds instead of externalizing them
Makes it impossible to tune sensitivity per category without a full redeploy, killing the policy team’s ability to react quickly.
Best Practices and Common Mistakes
Externalize thresholds & rules
Keep confidence thresholds and rule definitions in a config service or feature-flag system so policy teams can tune sensitivity without an engineering deploy.
Close the human feedback loop
Every reviewer decision — approve, delist, or overturn on appeal — should flow back as a labeled training example for the next model iteration.
Shadow-test new models
Always run a new model version silently alongside production before it makes real decisions, comparing its outputs against the current model and against eventual reviewer ground truth.
Risk-tier your categories
Not all product categories carry equal counterfeit risk; apply stricter synchronous checks and lower auto-approve thresholds for high-risk categories like luxury goods, electronics, and pharmaceuticals.
Design for explainability from day one
Store the specific rule and score that drove every decision; retrofitting explainability after regulators or legal teams demand it is far more painful.
Plan reviewer capacity using queueing theory
Use Little’s Law and historical traffic patterns to forecast reviewer staffing needs ahead of known peak events, not reactively.
Treating this as a “build it once” project. Counterfeiters actively study what gets caught and adapt within days. Detection systems in this domain require an ongoing operational commitment — regular model retraining, rule updates, and red-team style internal testing where your own team tries to evade the system to find blind spots before real bad actors do.
Real-World and Industry Examples
Project Zero & Brand Registry
Amazon runs “Project Zero” and a Brand Registry program where verified brand owners upload reference product images and can directly report and remove counterfeit listings, feeding a continuously-retrained ML detection pipeline that scans listings before and after publication.
Big-data IP protection platform
Alibaba operates a large-scale image-recognition and big-data risk-control system that reportedly scans a very high percentage of new listings using deep learning models trained on historical enforcement actions, combined with a dedicated intellectual-property complaint platform for rights holders.
Authenticity Guarantee
eBay uses a combination of seller-verification programs, an “Authenticity Guarantee” service involving physical inspection for certain high-value categories (like watches and sneakers), and automated listing screening for policy-violating keywords and images.
Seller verification + IP scanning
Given its handmade-goods focus, Etsy places heavy emphasis on seller identity verification and policy compliance scanning (banned materials, IP-infringing “fan art” reproductions) alongside standard image and text screening.
“How would a rights-holder verification program like Amazon’s Brand Registry integrate with the architecture we’ve discussed?” The brand owner’s verified reference images feed directly into the Vector Database as trusted “golden” embeddings. Any new listing whose image embedding matches a golden reference above a high similarity threshold, but whose seller is not the verified brand owner, becomes a very strong rule signal fed into the ML Scoring Service — essentially a high-confidence trademark-infringement detector layered on top of the general counterfeit pipeline.
17.1 A common pattern across all of these companies
Despite differing in scale, product mix, and regional footprint, every major marketplace converges on the same underlying architectural shape described in this tutorial: a fast, asynchronous ingestion path decoupled from a heavier detection pipeline; a layered defense combining deterministic rules with learned models; and a human review layer reserved specifically for the genuinely ambiguous cases where automation alone cannot be trusted with full confidence. The specific technologies differ — one company’s event bus might be a different messaging system than another’s, one company’s vector search might use a different indexing algorithm — but the shape of the solution, driven by the same fundamental constraints of scale, adversarial behavior, and asymmetric error costs, remains remarkably consistent. Recognizing this convergence is itself a valuable system design insight: when very different organizations independently arrive at similar architectures for the same class of problem, it is usually a strong signal that the architecture reflects genuine constraints of the problem itself, rather than an accident of any one company’s history.
Frequently Asked Questions
How do you handle a seller who keeps creating new accounts after being banned?
This is where the seller-risk graph becomes critical. New accounts are cross-referenced against banned accounts by shared signals — device fingerprints, IP ranges, bank account or payout details, and shipping addresses. A strong match against a previously banned identity can trigger an immediate high-risk flag even before the account lists a single product.
What stops the system from being biased against sellers from a particular region or price tier?
Regular fairness audits comparing false-positive rates across seller segments (region, account age, price tier) are essential. If low-price sellers are disproportionately flagged, that could reflect genuine risk correlation or model bias, and needs careful investigation with domain experts and, where needed, feature reweighting or threshold adjustments per segment.
How quickly can the system adapt to a brand-new evasion technique?
Rule updates can go out within minutes through the externalized rules configuration. ML model retraining is slower (days to weeks depending on how much new labeled data is needed), which is why the layered rules-plus-ML approach exists — rules provide a fast-reacting stopgap while the model catches up on the broader pattern.
Does the system scan listing edits, not just new listings?
Yes — a seller could publish a legitimate listing and later swap the photo or description to something prohibited. Every meaningful edit re-triggers the full detection pipeline, treated as a new event on the same listing id.
How does the system handle a product that is legal in one country but prohibited in another?
Rules and even certain model thresholds are parameterized by the shopper’s and seller’s region. The Rules Engine evaluates a region-aware rule set, so a listing visible to buyers in one country can simultaneously be blocked from appearing to buyers in a country where that product category is restricted, without needing two entirely separate detection pipelines.
What happens when the model’s accuracy degrades due to data drift?
Ongoing monitoring of the score distribution and reviewer-overturn rate (described in the monitoring section) surfaces drift early. When drift is confirmed, the team retrains on the most recent labeled data, validates the new model in shadow mode against live traffic, and only promotes it to production through a canary rollout once its precision and recall on recent data meet or exceed the current model’s.
How is this different from generic content moderation (like detecting spam or hate speech)?
The underlying multi-modal ML techniques (text and image classification) overlap significantly, but this domain adds unique signals — seller reputation graphs, price-anomaly detection against real-world market prices, and brand-reference matching — that generic content moderation systems typically do not need.
Summary and Key Takeaways
What we covered
- The scale problem: millions of daily listings make manual review impossible, demanding an automated, layered detection pipeline.
- Core building blocks — perceptual hashing, embeddings and vector search, rules engines, ML scoring, and confidence-based routing to human review.
- A full architecture with API Gateway, Load Balancer, event-driven ingestion, parallel feature extraction (image, text, seller risk), an ML scoring service, and a Decision Service routing to auto-approve, auto-delist, or human review.
- Reliability patterns — circuit breakers, graceful degradation, idempotent event processing, and the outbox pattern for atomic decision recording.
- Scaling techniques grounded in Little’s Law for review-queue capacity planning, and sharded, cached, and batched infrastructure for the heavier ML and vector-search stages.
- The ongoing operational reality: this is a continuously adapting system, not a one-time build, because the adversary keeps evolving.
A great counterfeit-detection architecture is judged not by how it performs on day one, but by how gracefully it degrades under load and how quickly it adapts when attackers change their tactics.
If you take away only one idea from this entire tutorial, let it be this: every architectural decision here — the choice to process listings asynchronously, the choice to layer deterministic rules underneath a learned model, the choice to route only the genuinely ambiguous cases to a human, the choice to fall back gracefully when any single dependency fails — traces back to the same two constraints stated at the very beginning. The system must operate at a scale where manual review of every item is economically impossible, and it must do so against an adversary that is actively trying to defeat it. Once you internalize those two constraints, most of the specific design choices in this tutorial stop looking like arbitrary engineering preferences and start looking like the natural, almost inevitable consequences of the problem itself. That is the mark of a well-reasoned system design: not a clever collection of unrelated tricks, but a small number of guiding principles applied consistently across every layer of the stack.