Extracted Topic
Software architecture as a distinct engineering discipline (system-level structuring, decomposition, trade-off reasoning, and decision documentation) - chosen because it is the single argument every other section of the post (design-vs-architecture, decomposition, protocols, data modeling, ADRs, C4) is built to support.
The Vital 20%
- The design-vs-architecture altitude distinction (bounded/reversible vs. system-wide/expensive-to-reverse decisions)
- System decomposition trade-offs: monolith vs. modular monolith vs. microservices vs. serverless
- Synchronous vs. asynchronous communication trade-offs (REST/gRPC vs. message queues) and the idempotency problem async creates
- Data modeling as the highest-cost-to-reverse layer (schema design, CQRS, event sourcing)
- Explicit trade-off reasoning using the CAP theorem and latency-vs-throughput / consistency-vs-availability framing
- Architecture Decision Records (ADRs) as the mechanism that preserves trade-off reasoning over time
- The C4 model as a lightweight way to externalize and communicate architectural assumptions
- Recognizing and avoiding over-engineering / one-size-fits-all decomposition by starting from actual constraints
20-Hour Plan
Session 1 - Distinguish a design decision from an architecture decision in your own codebase
- Core concept(s): Design (tactical, bounded, reversible) vs. architecture (strategic, system-wide, expensive to reverse); the building-blueprint analogy
- Resource(s): Martin Fowler, "Software Architecture Guide" (martinfowler.com/architecture/); Robert C. Martin, Clean Architecture (Prentice Hall, 2017), Introduction and Part I
- Hands-on task: Pick a real codebase you work in. List 10 recent changes and classify each as "design" or "architecture" using scope + reversal-cost as the test; flag any you classified based on gut feel and re-justify them.
- 15-min review:
- What two properties (not "size of change") determine whether something is architecture vs. design?
- Name one change from your list you initially misclassified, and why.
- Could you redesign a "room" (module) in your system without touching the "building" (system shape)? Give a concrete example.
Session 2 - Draw clean module boundaries using separation-of-concerns and bounded contexts
- Core concept(s): Modularity and separation of concerns; SOLID (single responsibility in particular); DDD bounded contexts
- Resource(s): Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software (Addison-Wesley, 2003), Part II on the Ubiquitous Language and bounded contexts; Martin Fowler, "BoundedContext" (martinfowler.com/bliki/BoundedContext.html)
- Hands-on task: Take one entangled module from your own system (or a public open-source repo) and sketch two or three bounded contexts it should probably be split into, based on "what changes for different reasons," not file structure.
- 15-min review:
- What's the practical test for whether two pieces of logic belong in the same bounded context?
- Name one place your sketch would have been wrong if you'd used file/folder proximity instead of "reasons to change."
- Why does clean modularity reduce risk for a later decomposition decision, rather than replacing the need for one?
Session 3 - Choose a system decomposition strategy justified by actual constraints, not preference
- Core concept(s): Monolith vs. modular monolith vs. microservices vs. serverless; operational-complexity-vs-autonomy trade-off
- Resource(s): Martin Fowler, "MonolithFirst" (martinfowler.com/bliki/MonolithFirst.html); Sam Newman, Building Microservices (O'Reilly, 2nd ed. 2021), Chapter 1
- Hands-on task: For a system you know (current job or a side project), write a one-page justification for its current decomposition using only measured constraints: team size, deployment frequency per component, and failure-blast-radius incidents. Then write what decomposition you'd recommend for a hypothetical 5-person team building the same product.
- 15-min review:
- What concrete signal (not "best practice") would justify splitting a module into its own service?
- Why would applying microservices to a 5-person team likely produce a "distributed monolith with extra latency"?
- What does a modular monolith preserve that a tangled monolith forecloses?
Session 4 - Pick a communication protocol based on the coupling/latency/decoupling trade-off it implies
- Core concept(s): Synchronous protocols (REST, gRPC) vs. asynchronous messaging (Kafka, RabbitMQ, SQS); coupling vs. decoupling trade-off
- Resource(s): gRPC official documentation, "Introduction to gRPC" (grpc.io/docs/what-is-grpc/introduction/); Apache Kafka documentation, "Introduction" (kafka.apache.org/documentation/#introduction)
- Hands-on task: For one real interaction between two services (yours, or a hypothetical order-processing flow), write out the trade-off explicitly: what you gain and lose choosing synchronous REST vs. an async queue, in terms of latency, coupling, and failure handling - no code yet.
- 15-min review:
- What does synchronous REST give you that async messaging doesn't, and vice versa?
- When would gRPC be preferred over REST specifically?
- What operational cost (name two) does choosing a message queue add that a synchronous call doesn't have?
Session 5 - Implement an idempotent async processing path and explain why async requires it
- Core concept(s): Idempotency in asynchronous processing; duplicate delivery as a consequence of choosing async for fault tolerance
- Resource(s): The blog post's own
OrderIngestionServiceTypeScript example (idempotency store guarding against duplicate order processing) as the primary worked reference; Apache Kafka documentation section on delivery semantics ("Message Delivery Semantics," kafka.apache.org/documentation/) - Hands-on task: Implement a minimal version of the
OrderIngestionServiceexample yourself (in-memory queue and idempotency store are fine) and write a test that simulates a redelivered message, proving your implementation doesn't double-process it. - 15-min review:
- Why does choosing async processing for fault tolerance implicitly create a duplicate-delivery problem?
- What does an idempotency store actually check before doing work?
- What real-world failure (name one) happens if you skip this in production?
Session 6 - Model data for a system's actual read/write and consistency needs
- Core concept(s): Data modeling as the highest-cost-to-reverse layer; CQRS; event sourcing
- Resource(s): Martin Fowler, "CQRS" (martinfowler.com/bliki/CQRS.html); Greg Young, "CQRS and Event Sourcing" (conference talk, widely available as "Greg Young CQRS" on YouTube, e.g. Code on the Beach 2014)
- Hands-on task: Take a read-heavy feature you know well (a feed, a dashboard, a report) and sketch a CQRS split: what the write model looks like, what the read model looks like, and what would have to change if you added event sourcing underneath it.
- 15-min review:
- Why is a data model harder to reverse than a communication protocol choice, once real data exists?
- What specific problem does CQRS solve that a single unified model doesn't?
- Where would event sourcing add cost without adding benefit in your sketch?
Session 7 - Use the CAP theorem to make one consistency/availability trade-off explicit and defensible
- Core concept(s): CAP theorem; consistency vs. availability under partition; latency vs. throughput
- Resource(s): Eric Brewer, CAP theorem (originally presented at PODC 2000); Seth Gilbert & Nancy Lynch, "Brewer's Conjecture and the Feasibility of Consistent, Available, Partition-Tolerant Web Services" (ACM SIGACT News, 2002) - both cited directly in the source post's references
- Hands-on task: For your CQRS sketch from Session 6 (or any distributed component you own), write down: what happens to each side (consistency, availability) during a network partition, which one you'd choose, and why - as if writing the "Consequences" section of a decision record.
- 15-min review:
- State the CAP trade-off in your own words without using the word "theorem."
- Why is CAP a structural constraint rather than an engineering-effort problem?
- Give one concrete example of a system that should favor availability, and one that should favor consistency.
Session 8 - Write an ADR that would prevent a real trade-off from being silently reversed
- Core concept(s): Architecture Decision Records (context, decision, alternatives considered, consequences)
- Resource(s): Michael Nygard, "Documenting Architecture Decisions" (cognitect.com/blog/2011/11/15/documenting-architecture-decisions) - the original ADR proposal, cited directly in the source post
- Hands-on task: Write one real ADR for the trade-off you made explicit in Session 7 (or any past team decision you can reconstruct), following Nygard's format exactly. Have a colleague read only the ADR and try to argue against the decision - see if the ADR's "Consequences" section actually holds up.
- 15-min review:
- What four sections does Nygard's original ADR format include?
- What failure mode does writing this ADR down actually prevent, precisely?
- What's the difference between "revisiting" a documented decision and "accidentally reversing" it?
Session 9 - Diagram a system's context and containers before changing it
- Core concept(s): The C4 model (Context, Containers, Components, Code); diagramming as a way to surface mismatched assumptions early
- Resource(s): Simon Brown, "The C4 Model for Visualising Software Architecture" (c4model.com) - primary source, cited directly in the post
- Hands-on task: Draw a Context and a Container diagram (pen-and-paper or a tool like Structurizr, which Simon Brown also maintains) for a system you're about to change or already own. Show it to one other engineer and note any assumption they disagreed with.
- 15-min review:
- What question does a Context diagram answer that a Container diagram doesn't?
- What's one assumption your reviewer flagged that you hadn't written down anywhere before?
- Why is drawing this diagram before building cheaper than discovering the mismatch three sprints in?
Session 10 - Critique a real engineering case study and identify which of the five common pitfalls it avoided or fell into
- Core concept(s): Applying the full stack (decomposition, protocols, data modeling, trade-offs, ADRs, C4) to a real system; the five pitfalls: over-engineering, undocumented decisions, ignoring the domain, reinventing the wheel, one-size-fits-all
- Resource(s): Netflix Technology Blog (netflixtechblog.com), Uber Engineering Blog (uber.com/blog/engineering/), and Shopify Engineering Blog (shopify.engineering) - pick one recent architecture-focused post from any of these three
- Hands-on task: Read one real case study end-to-end and write a half-page critique: what constraint actually drove their decision (not what pattern they used), what they traded away, and which of the five pitfalls they visibly avoided or risked falling into.
- 15-min review:
- What was the actual constraint (scale, team size, latency budget, failure tolerance) behind their headline decision?
- Which of the five pitfalls (over-engineering, no documentation, ignoring domain, reinventing the wheel, one-size-fits-all) is most visibly avoided in this case study, and how do you know?
- If your own team copied their specific pattern without checking constraints, what's the likeliest way that goes wrong?
What This Plan Deliberately Skips
This plan omits deep dives into specific pattern catalogs (full GoF catalog, GRASP beyond responsibility assignment basics), vendor-specific tooling (Kubernetes, specific cloud provider architectures), and the "expert" milestone skills of organizational coaching and technical-debt-portfolio management, since these build on - rather than constitute - the vital 20% above.