Blog 24
Designing for AI/ML Systems
Every system in this series moved data.
This one moves data through a component that costs a fortune to run, answers differently every time, holds more state in memory than the data itself, and can be confidently, fluently wrong.
The primitives don't change. The constraints do.
Twenty-three articles built a way of thinking. This final one points it at the frontier — the infrastructure behind large-scale machine learning and generative AI — and asks the question the whole series was preparing you for: when the hardest new systems arrive, does the method still hold?
It does. That's the finale's real lesson. An ML serving system is still caching (Part 6), still queues (Part 7), still storage (Part 8), still stateless scaling (Part 9), still load balancing (Bonus E), still failure design (Part 22). The C.R.E.D discipline runs on it unchanged. But the constraints are genuinely new — new enough to stretch every primitive to a shape you haven't seen — and naming exactly where the familiar meets the strange is the work of this article.
One honesty note up front: this is the one topic in the series that is moving as you read it. The specific frameworks, hardware, and techniques shift month to month. So this article teaches the shape — the durable constraints and the design responses to them — and flags where the details are current-as-of-writing and worth checking. The shape outlives the specifics.
Same walkthrough spirit, one last time. Let's meet the frontier.
Why AI/ML Systems Break Familiar Assumptions
Four assumptions this series quietly relied on — and how ML systems break each.
Requests were cheap and roughly equal. Now they're expensive and wildly unequal. A URL redirect cost microseconds; two redirects cost the same. An LLM request can cost a hundred milliseconds or thirty seconds depending on how many tokens it generates, and each one occupies scarce, costly GPU time. Bonus A's estimation still applies, but the unit economics inverted: compute, not storage or bandwidth, is the dominant cost, and it's the thing you're rationing.
Responses were deterministic. Now they're not. Every prior system, given the same input, returned the same output, which is why caching worked and testing was tractable. A generative model returns something different each time, can be confidently wrong (hallucinate), and has no single "correct" answer to check against. This breaks caching, testing, and the very definition of "correct" that Part 18 fought so hard for.
State lived in databases. Now enormous state lives in GPU memory, mid-request. Part 9's stateless dream assumed the important state was in a shared store. But generating a response builds up a large, per-request working state (the KV cache) that lives in GPU memory for the duration of that request, and it's often bigger than the model itself at long context. The "stateless compute" primitive meets a component that is aggressively, expensively stateful while it works.
The bottleneck was compute or I/O. Now it's memory bandwidth. The most counterintuitive break: during generation, the GPU is mostly idle, waiting for data to stream from its memory. LLM inference during token generation is memory-bandwidth bound, not compute-bound — the expensive compute chip sits largely unused while it waits on memory. This is well-established and consistently confirmed across current serving research: the decode phase reads model weights and the growing KV cache for every single token, and that data-movement cost, not the matrix multiplication itself, sets the pace. Every serving optimization is really an attack on that one fact.
These four breaks don't invalidate the series' primitives. They bend them, and the bending is the whole design.
The Simple Mental Model: A Brilliant, Expensive, Forgetful Consultant
Picture hiring a consultant who is extraordinarily capable but comes with peculiar constraints. They charge by the minute, and they're expensive, so you never want them idle, and you never want them doing work a cheaper assistant could do (GPU cost, batching, routing simple queries to small models). They answer from memory, and their memory is fixed at hiring — they don't know anything that happened after their training, and they'll confidently make things up rather than admit a gap (knowledge cutoff, hallucination, the case for retrieval). They think out loud, one word at a time, and to produce each next word, they re-read everything said so far (autoregressive generation, the KV cache that grows with the conversation). They can only hold so much in their head at once; give them too long a briefing and the earliest parts fall out (the context window). And they're brilliant but occasionally, fluently wrong, so for anything that matters, you check their work (evaluation, guardrails, humans in the loop).
Almost every design decision in ML systems is managing this consultant: keeping them busy but not overwhelmed, giving them the right documents instead of trusting their memory, and verifying the output because "confident" and "correct" are not the same thing.
The Two Worlds: Training vs Inference
The first clarifying split, because they are almost entirely different systems (and this article focuses on the second):
| Training | Inference (serving) | |
|---|---|---|
| Job | Build the model | Use the model to answer requests |
| Shape | Massive batch compute job | Latency-sensitive online serving |
| Duration | Runs for hours/days/weeks | Runs per request, must be fast |
| Optimizes for | Throughput above all | Latency AND throughput both matter |
| Series analog | Part 20's batch world, at extreme scale | Parts 13–17's online serving world |
| Cadence | Occasional, scheduled | Constant, user-facing |
Training is a batch data-processing problem (Part 20's world at extreme scale): enormous datasets, distributed compute across many GPUs, checkpointing so a multi-day job survives a machine death (Part 8's durability, Part 22's failure design — a training run that can't resume from a crash wastes a fortune). It's fascinating, and it's largely not what most engineers build.
Inference is an online serving problem, and it's the one this article designs, because it's where most engineers actually work: taking a trained model and serving it to users, fast, reliably, and affordably. Everything below is inference.
Step 1–3: Clarify, Requirements, Estimate (the Method Still Runs)
The C.R.E.D reflex applies unchanged, with ML-specific questions.
Clarify: are we training or serving? Self-hosting an open model or calling a provider API? Real-time (a chatbot) or batch (overnight document processing)? What quality bar, and how do we even measure "quality" for a non-deterministic system? Is retrieval needed (does the model need knowledge it wasn't trained on)?
Requirements (Bonus B, with new rows): latency now splits into two numbers — time-to-first-token (does it feel responsive?) and tokens-per-second (does it stream smoothly?) — because a streaming response has two different "speeds." Throughput is requests/sec and tokens/sec, since GPU utilization is the cost story. Cost, measured in dollars per request or per million tokens, is the dominant NFR here. Quality needs an evaluation strategy, since there's no single correct answer. Freshness asks whether the system needs current knowledge, which points at retrieval (RAG), below. And safety means guardrails on input and output, non-optional for anything user-facing.
Estimate (Bonus A, new units): the arithmetic that shapes everything is GPU economics. A model of a given size needs a certain amount of GPU memory just for its weights; each concurrent request needs additional memory for its KV cache; and a GPU serves only so many tokens per second. So the estimate is: how many GPUs, serving how many concurrent requests, at what cost per token? Inference compute dominates total cost of ownership, so unlike every prior system where storage or bandwidth drove the bill, here the estimate is fundamentally "how do we keep expensive GPUs busy enough to be affordable?" That single question drives the entire serving design.
The Core Serving Problem: Keeping Expensive GPUs Busy
Here is the design's center of gravity, and it follows directly from the estimate. GPUs are expensive and often underutilized during inference (the memory-bandwidth problem — the chip waits on memory). So the entire serving architecture is organized around one goal: maximize useful work per GPU-second, because idle GPU time is money burning.
Three techniques do most of the work, and each is a familiar primitive, bent.
Batching: Part 7's Load-Leveling, on a GPU
Processing requests one at a time wastes the GPU horribly. Batching runs many requests together, using the hardware's parallelism, but naive "static" batching makes everyone wait for the slowest request in the batch to finish. The modern answer is continuous batching: dynamically slot new requests in as others complete, keeping the GPU saturated. This is now the standard default in production serving stacks, and the throughput gain over static batching is substantial and well documented across current benchmarks.
This is Part 7's load-leveling and Bonus E's fair scheduling, fused and moved onto the GPU — the queue-and-workers pattern, where the "worker" is a GPU and the scheduling decision is which requests share a forward pass.
The KV Cache: The Memory Problem That Defines Serving
When a model generates text, it builds up a KV cache — the stored intermediate state for every token so far, so it doesn't recompute the whole sequence for each new token. This cache is the per-request state from the "forgetful consultant" model, and it has a brutal property: its memory footprint scales linearly with context length, and at long context the KV cache can be bigger than the model's own weights.
That single fact reshapes serving. GPU memory is split between model weights (fixed) and KV cache (grows with every concurrent request and every token). So the number of requests you can serve at once is memory-bound, and managing the KV cache efficiently — packing it, compressing it, reusing shared prefixes — is the difference between serving 8 requests and 80 on the same hardware. The current production substrate for this — paged, non-contiguous KV storage, now shipped across the major serving frameworks — is essentially Part 8's object-storage insight: store in scattered blocks, index the location, applied to GPU memory.
Model-Level Cost Levers
Beyond scheduling and memory, two levers reduce the raw cost of each inference: quantization (running the model at lower numerical precision — smaller, faster, cheaper, at a small accuracy cost, a direct Bonus C trade-off), and routing (sending simple queries to a small cheap model and reserving the big expensive one for hard queries — Part 10's routing and Blog 16's tiering, applied to models). Both are the series' cost-discipline instincts (Part 8's egress, Bonus A's imaginary-scale warning) meeting a component where compute is the bill.
The through-line: ML serving is the queue-cache-scale-cost playbook you already know, re-centered on the one resource that dominates everything — the GPU.
Deep Dive: RAG — Giving the Model Knowledge It Doesn't Have
The forgetful consultant's biggest limitation: their knowledge is frozen at training time, and they'll confidently invent answers to fill gaps. Retrieval-Augmented Generation (RAG) is the dominant architectural answer, and it's the most system-design-heavy pattern in modern AI, because it's mostly not about the model at all.
The idea: instead of trusting the model's frozen memory, retrieve relevant documents at request time and hand them to the model as context. Unlike static LLMs, RAG systems can access the latest documents at inference time, and, critically for trust, they can cite the documents used to generate an answer. It's the difference between asking the consultant to recall a regulation from memory and handing them the current regulation to read.
The pipeline, and notice how much of it is classical system design:
OFFLINE (indexing — a batch pipeline, Part 20):
documents → chunk them → embed each chunk into a vector →
store vectors in a VECTOR DATABASE (a new specialized store)
ONLINE (per request):
user query → embed it → SEMANTIC SEARCH the vector DB for similar chunks →
RE-RANK the candidates (Blog 16's staged ranking!) →
assemble query + top chunks into a prompt →
send to the model → generate answer with citations
Three things a system designer should see immediately.
The vector database is a new specialized store — Bonus H, extended. It indexes embeddings (numerical meaning-vectors) and answers "what's semantically similar to this?", a different query shape than any store in the series. It's the polyglot-persistence lesson again: the right store for a new data shape, sitting alongside your source of truth, never replacing it. And it has its own scaling story (partition the vectors, replicate for availability — Bonus G and Bonus I, on a new data type).
The retrieval pipeline is Blog 16's ranking, reborn. Retrieve a candidate set, then re-rank to the best few — the exact staged-ranking pattern from feeds and recommendations, because it's the same problem: too many candidates, a tight budget, spend the expensive scoring only on survivors. A cross-encoder scores query-document pairs and narrows to the top most relevant chunks.
And most RAG failures are infrastructure failures, not model failures. The uncomfortable truth: the model is often the reliable part. The retrieval is where it breaks, and with a uniquely nasty failure mode. A failed database node produces an error; a drifted vector index produces wrong answers that look correct — silent accuracy degradation, invisible at the application layer until someone notices the outputs are subtly wrong. This is Part 12's observability lesson at its sharpest: a system that fails loudly is a solved problem; one that fails silently and confidently is the dangerous one.
RAG, in one line: it's a search-and-ranking system (Parts 16–17) feeding a generation step, and the search half is where the system design lives.
Deep Dive: The New Failure Modes
Part 22 taught designing for failure. ML systems bring failures that don't exist anywhere else in the series, and the discipline extends to meet them.
The model is confidently wrong (hallucination). Not a crash, not an error — a fluent, plausible, wrong answer. There is no exception to catch. The design responses are architectural: ground the model in retrieved facts (RAG), cite sources so users can verify, constrain outputs where possible (structured formats, validation), and keep a human in the loop for high-stakes decisions. This is Part 21's "fail closed on ambiguity" in a new costume — for consequential outputs, an unverifiable answer is treated as suspect, not trusted.
Non-determinism breaks caching and testing. The same input yields different outputs, so Part 6's exact-match caching doesn't directly apply; you cache at the edges instead (identical-prompt caching, semantic caching of similar queries, cached retrieval results, cached KV prefixes). And testing shifts from "assert exact output" to evaluation — scoring quality across a suite, because there's no golden string to match. The correctness discipline from Part 18 doesn't vanish; it moves from equality to evaluation.
Quality degrades silently. A model or a vector index can drift — subtly worse answers, no error raised. This demands ML-specific observability: evaluation metrics tracked continuously, not just latency and errors. Part 12's "you can't fix what you can't see" reaches its hardest case, because here the failure is invisible by default.
Cost runs away. A prompt that's too long, a retrieval that pulls too much context, a retry loop on an expensive model — each quietly multiplies GPU spend. Cost observability (Part 12, Bonus A) becomes a first-class production metric, because in ML systems the bill can multiply from a bug that raises no error at all.
Prompt injection is a new security surface. User input becomes part of the model's instructions, so a malicious input can try to override those instructions ("ignore previous instructions and…"). This is a genuinely new class of vulnerability (Part 11 had nothing quite like it): the data and the control plane blur. Defenses — input/output filtering, privilege separation, treating model output as untrusted — are an active, evolving field, and this is one area where "solved" would be an overstatement.
And the familiar ones still apply. GPUs die (Part 22's redundancy), providers rate-limit and go down (Bonus E's failover, circuit breakers, fallbacks — fall back to a smaller model or a cached answer), requests time out (Part 22's timeouts on generation), and load spikes (Part 9's autoscaling, though GPU autoscaling is slow and expensive, so queuing and admission control from Part 18's flash-sale lesson matter more).
The synthesis: Part 22's failure discipline holds completely, and stretches to cover a model that fails by being wrong instead of by breaking.
Security, Safety, and Cost as First-Class Concerns
Three concerns that are elevated in ML systems from "important" to "defining."
Safety and guardrails. User-facing generative systems need input filtering (block malicious or abusive prompts) and output filtering (catch harmful, false, or policy-violating generations), a safety layer wrapping the model, not baked into it. For consequential domains, human review of outputs is architecture, not afterthought. This is defensive design (Part 11's spirit) applied to a component whose outputs are unpredictable.
Data privacy in a new dimension. User prompts may contain sensitive data; retrieved documents may be confidential; sending data to a third-party model API is a data-egress decision (Part 8's egress, now a privacy decision too). And a subtle one: data used to train or fine-tune a model can potentially be reflected in its outputs, a privacy surface with no analog in earlier systems. Part 11's tenant isolation and secrets discipline extend here, plus new questions about what data ever reaches the model.
Cost as the dominant NFR. Stated plainly because it's the recurring shock: in most systems, cost was a background concern; in ML serving, it's frequently the constraint that shapes the architecture. Every design lever above — batching, quantization, model routing, caching, prompt length, retrieval size — is partly a cost lever. The system that's technically excellent and economically ruinous fails (Bonus C's "expensive rehearsal for the redesign," at its most literal).
The Observability Plan
Part 12's table, extended with the metrics only ML systems have:
SLO: quality bar met + time-to-first-token target + cost/request ceiling
Latency: time-to-first-token, tokens/sec, end-to-end p99 (two-speed streaming)
Throughput: requests/sec, tokens/sec, GPU UTILIZATION (the cost efficiency metric)
Cost: $ per request, $ per million tokens, cost per user/tenant — FIRST-CLASS
Quality: continuous EVALUATION scores, hallucination/groundedness signals,
user feedback (thumbs up/down) — the silent-degradation smoke detector
Retrieval: retrieval relevance, re-rank quality, vector index freshness/drift,
retrieval latency (the RAG-specific health)
Safety: guardrail trigger rates, flagged inputs/outputs, injection attempts
Model: KV cache utilization, batch sizes, queue depth for GPU, GPU memory
Synthetic: a robot query with a KNOWN-good answer, run continuously —
the only way to catch silent quality regression
Two metrics get the highlight. GPU utilization is the cost story made visible — low utilization means you're paying for idle silicon, and every batching/caching optimization is measured here. And continuous evaluation is the smoke detector for the failure mode that has no error: quality drift is invisible until you measure it, so a suite of known-good queries scored continuously is not optional — it's the only defense against a system that gets quietly worse.
What Interviewers Actually Probe
"Design a chatbot / an AI-powered search / a RAG system." — clarify (serving not training, real-time, retrieval needed), estimate (GPU economics), design the serving path and the retrieval pipeline. The candidate who designs the vector DB, the ranking, and the caching, not just "call the model," has understood it. "How do you keep GPU costs down?" — batching, quantization, model routing, caching, prompt/context discipline; naming cost as the dominant NFR unprompted is the differentiator. "How do you handle hallucination?" — not "make the model better," but architecture: retrieval grounding, citations, output validation, human-in-the-loop for high stakes; it's a system design answer, not a model answer. "Why is the vector database its own store?" — a new data shape (embeddings, semantic search), Bonus H's polyglot lesson, extended, and it has its own failure mode: silent accuracy drift. "What breaks in a RAG system?" — the retrieval, usually, and silently; "most RAG failures are infrastructure failures" is the senior insight. "How is this different from a normal service?" — compute is the bottleneck and the cost, responses are non-deterministic, huge state lives in GPU memory, failure includes being confidently wrong; naming these four breaks is the answer.
The meta-move: treat the model as one expensive, unusual component inside a normal distributed system. The candidate who over-focuses on the model misses the interview; the one who designs the caching, queuing, retrieval, scaling, cost, and failure around the model, using every primitive from this series, is demonstrating exactly the transferable judgment the whole series was building.
What We Deliberately Didn't Build
The model itself — architecture, training, fine-tuning: a deep ML specialty; we designed the system around the model, which is the system-design job. Training infrastructure at depth — distributed training, gradient synchronization, checkpointing at scale: its own vast field (Part 20's batch world at the extreme); we scoped to serving. The embedding and ranking models — we used them as components (Blog 16's boundary again); their internals are ML, not system design. Prompt engineering — a real craft, but application-layer, not architecture. And the frontier of fast-moving specifics — exact serving frameworks, GPU hardware, and the month's newest optimization: named conceptually, deliberately not pinned, because they'll have moved by the time you read this. The shape is the durable lesson.
Common Mistakes Engineers Make with ML Systems
Treating it as a modeling problem, not a systems problem — the model is one component, the caching, retrieval, scaling, cost, and failure design around it are the actual work. Ignoring GPU economics until the bill arrives — cost is the dominant NFR, designing without it is designing a system the business can't run. Exact-match caching on non-deterministic output — the Part 6 reflex misapplied, cache retrieval, prefixes, and semantic matches instead. No evaluation strategy — testing for an exact string on a system that has no exact answer, quality drift then goes silently unnoticed. Trusting the model's memory instead of retrieving — hallucination on knowledge it never had, when RAG would have grounded it. Building RAG and monitoring only the model — the retrieval fails silently, most RAG failures are infrastructure failures nobody watched. No guardrails on a user-facing generative system — unfiltered input (injection) and unfiltered output (harmful/false generations), safety as an afterthought. Ignoring prompt injection — treating user input as trusted when it becomes part of the model's instructions. Static batching, or no batching — idle-GPU money burning, continuous batching is the modern default for a reason. Naive GPU autoscaling for spikes — GPU scale-up is slow and expensive, queuing and admission control (Part 18) often matter more than adding capacity. Over-engineering with AI where a normal system would do — the Bonus C/Bonus A discipline, at its most current: not every problem needs a model, and a model is the most expensive component you can add.
From My Journey: An Architectural Lesson
There's a temptation, approaching AI systems, to believe that everything is different now — that the arrival of models this capable means the old engineering knowledge no longer applies, and system design starts over from scratch. It's an understandable feeling; the models really are a genuinely new kind of component, and they really do break assumptions that held for the entire history of software.
But building these systems reveals something steadier underneath.
The realisation that reframes the whole frontier: the model is new, but the system around it is not. An AI application is still, overwhelmingly, a distributed system, with a cache, a queue, a specialized store, a scaling strategy, a cost model, and a failure plan. The model is one component in it: an unusually expensive, unusually stateful, unusually unpredictable component, but a component. And the work of making it fast, affordable, reliable, and safe turns out to be the exact work this series has been teaching all along — batching is load-leveling, RAG's retrieval is staged ranking, the vector database is polyglot persistence, hallucination-handling is fail-closed correctness, and cost discipline is the oldest lesson of all.
What's genuinely new is real, and worth respecting: compute as the dominant cost, non-determinism, memory-bound serving, silent quality failure, prompt injection. These stretch the primitives into shapes you haven't seen. But they stretch them — they don't replace them. The engineer who understands caching, queues, storage, scaling, consistency, and failure design is not starting over at the frontier. They're arriving with exactly the toolkit the frontier demands, needing only to learn where each tool bends.
The lesson that stuck, and it's the lesson of the entire series, in its final form: AI changes the hardest component in the system. It does not change the discipline of building the system around it.
Key Takeaways
- ML serving breaks four assumptions: requests are expensive and unequal, responses are non-deterministic, huge state lives in GPU memory mid-request, and the bottleneck is memory bandwidth, not compute.
- Training (batch, Part 20's world) and inference (online serving, this article's focus) are almost entirely different systems.
- The serving design's center of gravity is keeping expensive GPUs busy — batching (Part 7's load-leveling on a GPU), KV-cache management (the memory that defines capacity), quantization, and model routing.
- The KV cache grows with context and can exceed the model's own size — serving capacity is memory-bound, and managing it is the core optimization.
- RAG grounds the model in retrieved knowledge, and it's mostly a classical system: a vector database (polyglot persistence), staged ranking (Blog 16), and a batch indexing pipeline (Part 20).
- Most RAG failures are infrastructure failures, and the vector index fails silently, producing confident wrong answers (Part 12's hardest observability case).
- New failure modes stretch Part 22: hallucination (fail closed, ground, cite, human-in-loop), silent quality drift (continuous evaluation), runaway cost, and prompt injection.
- Cost is the dominant NFR — nearly every design lever is also a cost lever; the economically ruinous system fails.
- Observability adds ML-specific metrics: GPU utilization (cost efficiency), continuous evaluation (silent-drift detection), retrieval quality, and guardrail rates.
- The model is new; the system around it is not — every primitive in this series applies, stretched to a new shape.
Interview Lens
The ML system design interview rewards the candidate who refuses to be dazzled by the model, who treats it as one component in a system they already know how to build.
Design the system, not the model. When asked to "design a RAG chatbot," spend your time where the system design is: the retrieval pipeline, the vector store, the caching strategy, the GPU serving path, the cost model, the failure plan. Mentioning the model's internals is the trap; designing the infrastructure around it is the signal.
Lead with the constraints that are actually new. "The three things that change here are: compute is my dominant cost, responses are non-deterministic so caching and testing change, and failure includes being confidently wrong." Naming the real differences, not the hype, marks someone who has built these, not just read about them.
Reach for the series' primitives explicitly. "Batching is load-leveling; the vector DB is polyglot persistence; retrieval is staged ranking; hallucination-handling is fail-closed correctness." Showing that the frontier runs on familiar foundations is the most senior move available; it demonstrates transferable judgment, which is the entire point of learning system design.
The deepest signal: calm. The engineer who meets the newest, most-hyped systems with the same steady C.R.E.D method they'd bring to a URL shortener, clarify, estimate, design, scale, break, is demonstrating exactly what twenty-four articles were for. The frontier is not a reason to abandon the method. It's the method's hardest, best test.
Real-World Engineering Lens
Treat the model as a component, and build the system around it well. The caching, queuing, retrieval, cost control, and failure design are where most of your engineering leverage is; the model is often the most reliable part.
Instrument cost and quality from day one — they're your two new vital signs. GPU utilization and continuous evaluation catch the two failures unique to ML: money burning on idle silicon, and quality drifting silently. Neither shows up in latency-and-errors dashboards.
Ground and verify anything consequential. Retrieval, citations, output validation, and human review for high stakes — treat model output as untrusted until checked, exactly as you'd treat any input you don't control.
Monitor the retrieval, not just the model. In RAG, the silent failure is upstream of generation; a drifted index produces confident nonsense with no error. A known-good-query synthetic is your smoke detector.
Keep the C.R.E.D discipline. The newest systems reward the oldest method most: clarify scope, let the estimate (GPU economics) drive the design, name the trade-offs, and design for the failures, including the new one where the system is wrong instead of down.
The Series: Where We've Been, and Where You Go Now
Twenty-four core articles. Ten bonus deep-dives. One way of thinking.
Look back at the arc. A mindset — that failure is the default, that every choice is a trade-off, that requirements drive design (Parts 1–3). The building blocks — data, caching, messaging, storage, compute, APIs, security, observability, and the method to size and reason about them all (Parts 4–12, Bonuses A–J). Real systems, designed end to end — shorteners, notifications, chat, feeds, streaming, commerce, collaboration, infrastructure (Parts 13–20). The hardest problems — payments' provable correctness, resilience against inevitable failure (Parts 21–22). The performance — turning knowledge into judgment under pressure (Part 23). And the frontier — the newest systems, met with the same steady method (Part 24).
You didn't memorize architectures. You built an instrument: the ability to walk up to any system, one that exists, or one that doesn't yet, and reason about it calmly. Clarify what it must do. Estimate what it must handle. Design it against its real constraints. Choose consistency per data, name trade-offs and who owns them, place the state deliberately, and design the failures before they arrive. Then prove it's correct instead of assuming it.
That instrument doesn't go stale. Frameworks will change, this article's specifics most of all. Hardware will change. The trendy technologies will cycle, as they always have. But the discipline — clarify, requirements, estimate, design; trade-offs, consistency, failure, cost — is the durable core, and it's yours now.
The best system designers are not the ones who know the most systems. They are the ones who can reason clearly about any system, including the ones that don't exist yet.
There is no Part 25. There's just the next system you design, and now you know how.
Thank you for reading. Go build something that stays standing.