Mo Sharif
Back to writing

Learning System Design: Practice the Decisions

In this article

Knowing what a queue does is not the same as knowing whether your system needs one.

Building Codelit kept bringing me back to that gap. A clean explanation helps someone recognize a component. A useful exercise makes them decide where it belongs, what it costs, and what changes when it fails.

System design judgment

is the ability to connect an architectural choice to a specific constraint and explain its alternatives, costs, and failure behavior.

Component knowledge explains available tools; judgment connects those tools to the problem in front of you. A learner can define caching accurately and still apply it to a checkout path without considering stale inventory, authorization, or payment correctness.

That does not mean reading is ineffective or that engineers cannot learn concepts. It means the exercise should test the decision as well as the definition.

Take a slow checkout endpoint. Before adding a cache, ask where the time goes, which data can be stale, and whether the slow work belongs in the request at all. Each answer points to a different design.

Reading supplies models and vocabulary; practice reveals whether you can use them under new constraints. Pair the two instead of treating one as a replacement for the other. The goal is to explain a design, not reproduce its appearance from memory.

ActivityUseful question
Read a referenceWhich requirement justifies each major component?
Rebuild it without lookingWhat relationships did I forget or misunderstand?
Change a requirementWhich original decision no longer fits?
Introduce a failureWhich operation stops, degrades, or needs recovery?
Explain it to someone elseCan I defend the trade-off without naming a brand?

The patterns across Codelit's architecture templates are useful starting points. They are not verified replicas of every named company's current production system, and I would not present them as such.

A good exercise has explicit requirements, a manageable scope, and enough uncertainty to require a decision. It should let someone compare alternatives and explain why one fits, rather than reward whichever diagram contains the most recognizable infrastructure.

Try this sequence:

  1. Design a notification service with a clear delivery requirement.
  2. Identify what must happen before the API acknowledges a request.
  3. Decide what should happen when the email provider is unavailable.
  4. Increase traffic or tighten the delivery target.
  5. Revise the design and explain what changed.

Use an interactive canvas if it helps, or use paper. The tool matters less than whether the learner can trace data and failure paths.

Beginners benefit from checking four things early: requirements before tools, explicit data flow, realistic scale, and a failure path. These questions keep a design grounded without requiring deep knowledge of every database, queue, or cloud service.

Choosing infrastructure first. "Use Kubernetes and Kafka" is not a requirement. State the workload, reliability needs, team constraints, and operating environment before choosing them.

Distributing too early. A modular monolith may be easier to deploy and reason about. Multiple services should solve an identified problem, not signal that the design is serious.

Leaving arrows unexplained. Label whether a connection is synchronous or asynchronous, what moves across it, and what happens when it fails.

Copying scale. A reference architecture reflects constraints. Borrow the reasoning, not every component.

Experienced engineers should challenge assumptions that familiarity makes easy to overlook: inherited tools, future scale, operating cost, and ownership. A design can be technically sophisticated and still be a poor fit for the team that has to run it.

AssumptionReview question
We have always used this technologyWould we choose it again for this workload?
We will need global scaleWhat evidence determines when the design must change?
More services improve the systemWhich capability or ownership boundary requires the split?
A managed service removes operationsWhich reliability and cost responsibilities remain ours?
Cost can waitWhat assumptions dominate the monthly estimate?

Design-time cost estimates can sharpen that last conversation. They should carry inputs and uncertainty, not an unexplained monthly total.

Failure practice asks learners to explain what the design depends on and how it recovers. It turns a vague resilience claim into specific questions about retry behavior, capacity, data loss, and the operations that remain available.

Chaos mode can make those relationships visible, but the simulation only knows what the graph declares. A yellow node is not evidence that the deployed service can degrade gracefully.

Ask the learner to predict the result before running a scenario. Then compare the prediction with the model and inspect both. If they disagree, the lesson may be in the learner's reasoning or in a missing simulation assumption.

Retries are a good example. "Add retries" is not automatically the repair. Retrying an overloaded dependency can make an incident worse unless the design includes limits, backoff, and capacity controls.

AI helps by supplying a concrete draft that a learner can question. It can mislead when fluent explanations make unsupported choices look settled. The exercise needs a way to check the draft and a reason for the learner to think before accepting it.

I like using the prompt-to-diagram pipeline to reduce drawing friction, then asking questions the model's first answer did not resolve: why this consistency level, why this boundary, and what breaks during a dependency outage?

Do not call an AI mistake a teaching feature without a verification step. A beginner may not recognize the mistake. Provide a reference, review rubric, or knowledgeable feedback so the error can actually become a lesson.

One practical rule: write your requirements and first design before asking the model for alternatives. Then compare the decisions, not just the diagrams.

Look for transfer: can the learner explain a new design under changed constraints, identify uncertainty, and defend a simpler alternative? Recalling the reference's boxes is useful practice, but it is not the same as independent design ability.

Use the same rubric across exercises: requirements, data flow, trade-offs, failure behavior, cost, and verification. Ask for a revised explanation after feedback.

I do not have a controlled study showing that Codelit users learn faster or perform better in interviews. The claim I can defend is narrower: the canvas makes it easier to change a design and discuss the consequences.

That is the teaching direction I want to keep building toward. Less emphasis on the perfect reference diagram, more emphasis on the decisions a person can explain after the reference is gone.

Questions people actually ask

Why is knowing components not enough for system design?
Knowing what a component does is different from deciding whether a system needs it. Design requires linking a choice to a constraint, explaining the alternative, and recognizing its cost and failure behavior. Practice should test that reasoning, not just whether someone can name a cache or queue.
How can I practice system design?
Start with a requirement, sketch the simplest design that meets it, and explain the important data flows. Compare with a reference, then change one constraint and revise the design. Add a failure scenario and identify which assumptions need implementation or measurement to verify.
What are common system design mistakes?
Common mistakes include choosing tools before requirements, copying a large company's architecture without its constraints, leaving data flows unexplained, and drawing only the happy path. A useful review asks what each component provides, what fails without it, and whether a simpler choice would suffice.
Can AI help someone learn system design?
AI can supply a draft to critique and reduce the blank-page problem. It can also produce convincing mistakes, so generated designs need review against requirements and reliable references. Ask learners to make and defend their own choices rather than accepting a complete answer on trust.
Does a diagram failure simulation prove resilience?
No. It shows consequences under the dependencies and rules represented in the model. Use it to identify assumptions and propose experiments. A running system's resilience still needs implementation checks and controlled testing with a defined hypothesis, scope, and recovery plan.