all_lessons / system_design / 18 · archetypes lesson 18 / 19

System design archetypes — recognising the shape

Lessons 01–13 handed you mechanisms. An interview hands you a product. The senior move is to classify first: almost every prompt is, underneath, one of about eight recurring shapes — and the shape tells you the dominant force, the first bottleneck, and which mechanisms to reach for, before you draw a single box.

Here is the failure mode this lesson cures. A candidate is asked to "design Dropbox" and immediately starts sketching an API, a Postgres schema, a load balancer — generic boxes that fit any system and therefore commit to nothing. Forty minutes later there is a diagram but no argument: nothing in it follows from what Dropbox actually is. The senior candidate spends the first sixty seconds doing classification: "this is a blob/media system — large immutable objects, small hot metadata, durability-dominated — so the first decisions are object store vs metadata DB separation, chunked resumable uploads, and CDN delivery." Every box afterward is a consequence of that sentence.

The archetype is not the answer. It is a starting hypothesis that picks your default mechanisms and your default bottleneck. You then adjust with the real numbers from lesson 01 (requirements, QPS, data size) and the latency/throughput budget from lesson 02. Recognise the shape → inherit a design skeleton → tune it. That is the whole game.

One distinction to keep straight: this lesson decomposes a prompt into shapes (what kind of problem each piece is), which is not the same as decomposing it into services (a separate, deployment-level decision covered in lesson 17). A shape might end up as one module inside a larger service, or as its own deployable service — recognising the shape tells you the mechanisms; whether it earns its own service is a later call about team boundaries, scaling, and blast radius.

Real systems are composites
Almost nothing in production is a single shape. A social app is CRUD (profiles, settings) + feed/fanout (the timeline) + blob/media (photos/video) + search (discover people) + real-time (DMs, typing). The interview skill is to decompose the prompt into its shapes and design each with the right skeleton, rather than forcing one architecture onto everything. When you say out loud "this is really four shapes, let me take the dominant one first," you have already out-structured most candidates.

The eight archetypes at a glance

This is the taxonomy. Memorise the tells, not the rows — the tell is the word in the prompt that fires the classification.

System shapeCanonical exampleCore problem
1 · CRUD / transactionalbanking, user profilecorrectness, strong consistency
2 · Feed / fanoutTwitter, Instagramread amplification, fanout, hot keys
3 · Queue / async workersimage processing, emaildecoupling slow work, safe retries
4 · Streaming / logmetrics, clickstreamordered high-throughput ingest
5 · Search / retrievalGoogle, Yelpindexing + ranking
6 · Real-time coordinationchat, multiplayerlow-latency delivery, presence
7 · Analytics / OLAPdashboards, logslarge scans, aggregation
8 · Blob / mediaYouTube, Dropboxlarge objects + durability

1 · CRUD / transactional

Dominant force: getting the write right. Scale is usually modest (thousands of QPS, not millions); the hard part is invariants — an account balance must never go negative, an order must not be double-charged. Read:write: mixed, often write-significant. Consistency stance: strong, CP under CAP — you reject writes during a partition rather than accept a wrong balance. Go-to mechanisms: single-leader replication (one writer = a serialization point), ACID transactions with the related rows co-located on one shard so you never need a distributed commit, shard by entity id only when one node is genuinely too small. Canonical architecture: a relational store with the leader taking writes, read replicas for scale-out reads, transactional boundaries drawn around an aggregate so the common operation is single-shard. The tell: "money", "must not double-charge", "source of truth", "audit".

2 · Feed / fanout

Dominant force: read amplification plus the celebrity hot key. One write (a tweet) is read by millions; one user (a celebrity) has tens of millions of followers, so naive fan-out-on-write explodes. Read:write: extremely read-heavy (often 100:1 or more). Consistency stance: eventual — a few seconds of timeline staleness is fine. Go-to mechanisms: heavy caching, async fanout via queue, shard by user, and the hybrid fan-out strategy (push to most followers' timelines, pull for celebrities) fully developed in lesson 19. Canonical architecture: write to a per-user post store, fan out into per-user timeline caches asynchronously, serve the home feed from cache; merge celebrity posts at read time. The tell: "timeline", "home feed", "followers", "news feed".

3 · Queue / async workers

Dominant force: moving slow or spiky work off the request path so the synchronous API stays fast. Read:write: not the framing — think in jobs/sec produced vs consumed. Consistency stance: the user gets an immediate "accepted", the work completes later; the contract is at-least-once. Go-to mechanisms: a message queue with competing consumers, idempotency keys so a retried job is harmless, a dead-letter queue for poison messages, backpressure when producers outrun consumers, and worker autoscaling on queue depth. Canonical architecture: API enqueues a job and returns 202; a pool of stateless workers pulls, processes, retries, and DLQs. The tell: "process in the background", "send the email", "generate the thumbnail", "this can be slow".

4 · Streaming / log processing

Dominant force: sustained high-throughput ordered ingest, then continuous processing. Unlike a job queue (discrete tasks, any order), a log is an ordered append-only sequence you replay. Read:write: write-dominated ingest, often millions of events/sec; reads are sequential scans by consumer groups. Consistency stance: ordering matters per partition; end-to-end you aim for exactly-once processing via idempotent writes (12), not exactly-once delivery. Go-to mechanisms: a partitioned append-only log (Kafka-style), per-partition ordering with partition keys, consumer groups, windowed aggregation, usually feeding an OLAP store downstream. The tell: "events per second", "clickstream", "real-time metrics", "ingest pipeline".

5 · Search / retrieval

Dominant force: building and serving an inverted index — a map from term → the list of documents that contain it, the structure that powers search and retrieval — and the two-stage recall → rank pipeline. Read:write: read-heavy queries against an index that updates asynchronously. Consistency stance: eventual index freshness — new documents appear after the indexing pipeline catches up (seconds to minutes). Go-to mechanisms: an inverted index partitioned local (document-based) vs global (term-based) — the choice governs whether queries scatter to all shards or hit one, covered in lesson 07; read replicas + cached popular queries; an async indexing pipeline; scatter-gather across shards then a ranking stage. The tell: "search", "query", "relevance", "ranking", "autocomplete".

6 · Real-time coordination

Dominant force: many long-lived stateful connections, sub-second delivery, and presence. This is the deliberate exception to lesson 05's "make servers stateless": a connection server holds an open WebSocket per client, so it is inherently stateful. How you still scale it: a thin stateless routing/session layer maps a user to the connection server currently holding their socket (a directory in Redis), and a pub/sub backbone fans a message to whichever servers hold subscribers for that room. The connection servers are stateful but shardable and replaceable; on disconnect the client reconnects and the directory updates. Consistency stance: per-room ordering, eventual elsewhere. Presence is ephemeral heartbeated state (TTL keys), not durable. The tell: "online status", "typing indicator", "live", "presence".

7 · Analytics / OLAP

Dominant force: scanning huge volumes for aggregates, not point lookups. The cardinal sin is running these scans on the serving OLTP database. Read:write: read-heavy big scans, batch or near-real-time loads. Consistency stance: eventual freshness is acceptable ("as of 5 minutes ago"). Go-to mechanisms: columnar storage — a columnar store keeps each column contiguous on disk, so an analytical scan reads only the columns it needs (the ones a GROUP BY touches) rather than whole rows — OLAP physically separated from OLTP, lambda/kappa batch+stream pipelines, and pre-aggregation via materialized views / rollups so dashboards read summaries not raw rows. The tell: "dashboard", "report", "group by", "over the last 30 days", "ad-hoc queries".

8 · Blob / media

Dominant force: storing and serving large immutable objects cheaply and durably, while a small hot metadata set stays queryable. Read:write: write-once, read-many; objects are MB–GB, metadata is tiny. Consistency stance: object content is immutable (no update conflicts); metadata is strongly consistent and small. Go-to mechanisms: an object store (S3-style) fronted by a CDN for delivery; a separate metadata DB (07/08) — never store the blob bytes in your relational DB; chunking + resumable + presigned uploads so bytes go client→store directly; replication or erasure coding for durability; range reads for streaming. The tell: "upload", "video", "file", "GB-sized", "download/stream".

Worked example — why the Feed shape's bottleneck is fanout, quantitatively
Suppose 200M users, average 200 followers, and the median user posts twice a day. Total writes ≈ 200M · 2 = 400M posts/day ≈ 4,600 posts/sec — trivial. But each post must reach every follower's timeline. Under fan-out-on-write, write work ≈ 4,600 · 200 ≈ 920,000 timeline inserts/sec — a 200× amplification. Now add a celebrity with 100M followers: a single tweet schedules 100M inserts, a multi-minute write storm and a hot shard. That is precisely why the answer is hybrid: fan-out-on-write for ordinary users (cheap reads), and fan-out-on-read for the handful of celebrities (merge their posts at read time so one write isn't amplified 100M×). The numbers — not taste — force the split, and the read side stays a ≈ 10ms cache hit. Lesson 19 derives the crossover threshold.

Master table: shape → force → first bottleneck → headline mechanisms

The first table told you what each shape is. This one tells you what breaks first — the thing you should be defending in the design.

ArchetypeDominant forceBreaks firstHeadline lessons
CRUDwrite correctnesswrite contention on the leader / lock hotspots12 txns, 08 repl, 09 CAP
Feedread amplificationfanout fan-out cost + celebrity hot key06 cache, 11 queue, 07 shard
Queuedecoupling slow workqueue backlog / consumer lag, duplicate effects11 msg, 12 idemp, 05 scale
Streamingordered ingest throughputpartition throughput ceiling, consumer lag11 log, 07 part, 12 EOS
Searchindex build + rankindex size/fanout, ranking CPU, freshness lag07 index, 06 cache, 08 repl
Real-timeconnection count + latencyconnection memory, pub/sub fanout per room11 pubsub, 05 LB, 09 order
OLAPscan volumescan I/O / aggregation cost, OLTP contamination07 part, 11 pipe, 06 rollup
Blobobject size + durabilitystorage cost, egress bandwidth, durability06 CDN, 13 durab, 07 meta

How to classify in 60 seconds

Four questions pin the shape. Ask them out loud in the interview; the answers route you to a skeleton.

  1. Read:write ratio? Read-heavy points to Feed / Search / OLAP / Blob-read; write-heavy or balanced points to CRUD / Streaming-ingest / Queue.
  2. Consistency requirement — strong or eventual? Strong + correctness language → CRUD. Eventual-tolerant → almost everything else (feeds, search freshness, dashboards).
  3. Payload size — small rows or large blobs? Large objects (MB–GB) → Blob almost regardless of the other answers; small rows keep you in the row-shaped world.
  4. Interaction model — request/response, background job, continuous stream, or persistent connection? Persistent connection → Real-time; continuous high-volume stream → Streaming; fire-and-forget slow work → Queue; classic req/resp → CRUD/Feed/Search/OLAP depending on Q1–Q3.

The questions are ordered by discriminating power, which is why payload size and interaction model are asked early: they override the read:write ratio. A 4 GB video upload is a Blob system whether reads or writes dominate; a persistent-connection chat is Real-time regardless of consistency. Only after those structural signals do you let the read:write ratio and consistency requirement split the remaining request/response world (CRUD vs Feed vs Search vs OLAP). Concretely: read:write ≈ 100:1 + eventual + small + req/resp routes to Feed/Search; ≈ 1:1 + strong + small routes to CRUD; an "as of last 30 days, GROUP BY" phrasing routes to OLAP even at moderate read ratios.

And the meta-question: is it really several shapes? If the prompt names a whole product, decompose. "Design Instagram" = CRUD (accounts) + Blob (photos) + Feed (home) + Search (discover) + Queue (notifications). Pick the dominant shape to lead with and name the rest.

Worked example — classifying "design a metrics dashboard for a fleet of servers"
Walk the four questions with numbers. Q1 read:write: ingest is ~50k servers × 200 metrics every 10 s ≈ 50000 · 200 / 10 = 1,000,000 writes/sec — write-dominated ingest. Q2 consistency: "the dashboard as of a minute ago" is fine → eventual. Q3 payload: tiny numeric samples → small rows, not blobs. Q4 interaction: continuous high-volume ordered ingest on the write side, big GROUP-BY scans on the read side.

So this is a composite: the ingest half is Streaming (partitioned log keyed by server id, 11) and the query half is Analytics/OLAP (columnar store, pre-aggregated rollups so "p99 latency over the last 24h" reads a summary table, not 86M raw points). The link between them is a stream-processing job doing windowed rollups. Notice how naming two shapes immediately produced the architecture — log in front, OLAP behind, rollup job between — with zero box-drawing.

Decomposing a composite — a worked map

When the prompt is a whole product, do not pick one architecture; produce a shape inventory and assign each its skeleton. This is the single most senior-looking move in the first five minutes. Here is "design Instagram" decomposed:

Sub-featureShapeDominant force hereDefault skeleton
Accounts, profile, settingsCRUDwrite correctnesssingle-leader RDBMS, ACID, shard by user id
Photo/video storage + servingBlobobject size, egress, durabilityobject store + CDN, presigned chunked upload, metadata DB
Home feedFeedread amplification, hot keysper-user timeline cache, async hybrid fanout
Explore / hashtag searchSearchindex build + rankpartitioned inverted index, async indexing, query cache
Likes/comments countersStreaming + OLAPhigh-volume events → countsevent log → windowed rollups → counter store
Push notifications, transcodingQueueslow work off the request pathmessage queue, idempotent workers, DLQ
Live / DMs (optional)Real-timeconnection count, presenceWebSocket servers + session directory + pub/sub

Seven shapes, each with a default skeleton, derived in under a minute. You then declare the dominant one to design in depth (the feed) and treat the rest as named, defended components. The interviewer now knows you can both classify and compose.

The classification decision tree

Run the four questions top-down. The first matching rule wins, which is why blob and connection model are checked early — they dominate regardless of the read:write ratio.

PROMPT (a product or feature) | ┌─────────────────────┴──────────────────────┐ │ Q3: payload large blobs (MB–GB)? ── yes ──┼──→ [8] BLOB / MEDIA └─────────────────────┬──────────────────────┘ (object store + CDN + meta DB) │ no (small rows) ┌─────────────────────┴──────────────────────┐ │ Q4: persistent connection / presence? ─yes─┼──→ [6] REAL-TIME └─────────────────────┬──────────────────────┘ (WS + pub/sub + session dir) │ ┌─────────────────────┴──────────────────────┐ │ Q4: continuous ordered high-vol stream?─yes┼──→ [4] STREAMING └─────────────────────┬──────────────────────┘ (partitioned log + consumers) │ ┌─────────────────────┴──────────────────────┐ │ Q4: fire-and-forget slow background job?─y─┼──→ [3] QUEUE / WORKERS └─────────────────────┬──────────────────────┘ (queue + idempotent workers) │ request/response ┌─────────────────────┴──────────────────────┐ │ Q2 strong + Q1 write/balanced? ──── yes ───┼──→ [1] CRUD / TXN └─────────────────────┬──────────────────────┘ (single-leader + ACID) │ eventual + read-heavy ┌─────────────────────┴──────────────────────┐ │ big GROUP-BY scans / aggregates? ── yes ───┼──→ [7] OLAP │ ranking / inverted index? ──────── yes ───┼──→ [5] SEARCH │ follower timeline / fanout? ────── else ──┼──→ [2] FEED └─────────────────────────────────────────────┘

From shape to a 30-second skeleton

Once the shape is fixed, you inherit a default skeleton you can recite before drawing anything. The skeleton is deliberately generic so you can then specialise it with numbers:

Notice each skeleton is three to five boxes and follows mechanically from the shape. The interview value is that you can produce it instantly and then spend your time on the interesting decisions — the hot-key strategy, the rollup window, the durability scheme — rather than rediscovering the obvious topology. Each shape also carries a characteristic API shape (lesson 03): CRUD is resource-oriented REST, Queue exposes an async "accept now, 202, poll/callback later" contract, Blob hands out presigned upload/download URLs, and Real-time is a persistent bidirectional channel rather than request/response — so naming the shape also defaults your interface.

The confusable pairs — where classification goes wrong

Most misclassifications are between two shapes that look alike on the surface. Knowing the discriminator for each pair is what makes your snap classification reliable.

Try it: the archetype classifier

Set the four signals; the widget runs the same rule-based classifier as the tree above and tells you the most likely shape, its core problem, the dominant force, and the lessons to reach for. When the signals point at more than one shape it flags a composite — exactly when you should say "let me decompose this."

Archetype classifier
Logic (first match wins, matching the decision tree): large blobs → Blob; persistent connection → Real-time; continuous stream → Streaming; background job → Queue; otherwise (request/response) strong+small+write/balanced → CRUD; eventual+read-heavy with the "aggregation" toggle → OLAP, with the "ranking" toggle → Search, else → Feed. Ambiguous combos (e.g. strong consistency but read-heavy, or aggregation on a write-heavy req/resp) are flagged amber as composite.
Most likely archetype
Dominant force
Go-to lessons
Classification

Interview prompts you should be ready for

  1. "You're given 'design Twitter' — what's the first sentence out of your mouth?" (Classify before architecting: "It's dominantly a feed/fanout shape — read-amplified, eventually consistent, hot celebrity keys — plus CRUD for accounts and blob for media; I'll lead with the timeline." Naming the shape commits you to caching + async fanout + the hybrid push/pull strategy.)
  2. "How do you decide CRUD vs feed/fanout when both store posts?" (The discriminator is the read pattern, not storage: if the dominant query is 'fetch one entity by id and mutate it under an invariant' it's CRUD; if it's 'assemble a personalized read-amplified view from many writers' it's feed. Same rows, opposite bottlenecks.)
  3. "Real-time chat seems to violate 'keep servers stateless' — reconcile that." (It's the deliberate exception: connection servers must hold the socket, so they're stateful, but you keep them shardable behind a stateless session directory and fan messages via pub/sub. State lives in the connection layer and an ephemeral presence store, not in business logic; a dropped server just forces reconnect.)
  4. "A prompt says 'show p95 latency by region over the last 30 days on a live serving DB' — what's wrong and what's the shape?" (That's OLAP run on OLTP — large scans will contend with serving traffic and tank p99. Separate it: stream or batch into a columnar store, pre-aggregate rollups so the dashboard reads summaries. The fix is recognizing it as analytics, not a query-tuning problem.)
  5. "Where does streaming differ from a job queue — aren't both 'async'?" (A queue distributes discrete tasks with no ordering guarantee and competing consumers; a log is an ordered, replayable, partitioned sequence consumed by groups that track offsets. If ordering and replay matter — clickstream, CDC — it's streaming; if independent units of slow work — it's a queue.)
  6. "For 'design Dropbox', why not store files in Postgres?" (Blob shape: GB objects are immutable and cheap-to-store-but-expensive-to-serve, so they belong in an object store + CDN; the relational DB holds only small queryable metadata. Mixing blobs into the OLTP DB destroys its cache locality, backup time, and replication throughput.)
  7. "Give me a system that is genuinely a single archetype, and one that is a composite." (Single: a URL shortener is near-pure CRUD/KV with a read cache. Composite: Instagram is CRUD + blob + feed + search + queue. The senior signal is decomposing the composite and designing the dominant shape first while naming the others.)
  8. "Once you've named the archetype, what stops you from over-trusting it?" (It's a hypothesis, not a verdict — I re-derive with lesson 01/02 numbers. If 'feed' turns out to have only thousands of users, fan-out-on-read with no precompute is simpler; the archetype set my defaults, the numbers set the actual design.)
Takeaway
Eight shapes cover almost every interview prompt. Spend your first 60 seconds classifying — read:write, consistency, payload size, interaction model — because the shape names the dominant force, the first bottleneck, and the default mechanisms before you draw anything. Real products are composites: decompose into shapes, design the dominant one, name the rest. Treat the archetype as a starting hypothesis you then tune with real numbers. Next, lesson 19 takes the feed/fanout shape end to end.