Fundamentals of Software Architecture An Engineering Approach by Mark Richards, Neal Ford

December 27, 2024

🔰 Introduction: Understanding the Role of a Software Architect

The authors open with an observation:

“The job ‘software architect’ appears near the top of numerous lists of best jobs across the world.”

But unlike nurses or finance managers, there’s no clear path to becoming one.

Why? Because:

  1. There is no single, widely accepted definition of software architecture.
  2. The scope of the role has expanded immensely in recent years.
  3. Software architecture is a moving target—constantly evolving.
  4. Much existing literature is outdated or context-specific.

🧱 Defining Software Architecture: A Multifaceted View

“Architecture is about the important stuff… whatever that is.” — Ralph Johnson

Mark and Neal refuse to reduce architecture to a narrow definition. Instead, they build a layered conceptual model:


1. Structure of the System

  • This is the most visible layer: what architecture looks like.
  • Examples:
    • A microservices architecture (many independent services).
    • A layered architecture (presentation → business → data).
    • A monolith (all-in-one deployable unit).

“Describing an architecture solely by the structure does not wholly elucidate an architecture.”

Structure alone doesn’t explain the why or the rules behind it.


2. Architecture Characteristics (The ‘-ilities’)

These define non-functional success criteria:

  • Scalability
  • Availability
  • Performance
  • Maintainability
  • Security
  • Observability

📌 Example: Two systems may perform the same functions (e.g., an e-commerce platform), but if one crashes under load, it lacks availability and scalability—making its architecture unsuitable.


3. Architecture Decisions

These are explicit rules or constraints.

  • They are what makes or breaks your architecture.
  • Example: “Only the business layer may access the database.” This enforces layer isolation to prevent ripple effects.

“Architecture decisions define the rules for how a system should be constructed.”

They can also be technology-specific when needed, e.g., “We will use Kafka for asynchronous event communication.”


4. Design Principles

Unlike hard rules, these are guiding heuristics.

  • Example: “Prefer asynchronous messaging for internal service communication.”
  • They allow flexibility depending on the context.

“A design principle differs from an architecture decision in that it is a guideline rather than a hard-and-fast rule.”


🎯 Expectations of a Software Architect (Not Just a Title, But a Mission)

Rather than define the role, the authors focus on what architects are expected to do.


1. Make Architecture Decisions

  • An architect is expected to define the architecture decisions and design principles used to guide technology decisions within the team, the department, or across the enterprise.

“Guide is the key operative word.”

Instead of mandating:
❌ “Use React.js”
Architects should say:
✅ “Use a reactive front-end framework (e.g., React, Vue, Angular).”

🧠 Why? This empowers dev teams while aligning with architectural goals.

📌 Real-world example: If your architecture prioritizes performance, you may guide teams toward frameworks that support server-side rendering for faster page loads—e.g., Next.js.


2. Continually Analyze the Architecture

“Architecture vitality” measures how viable your design remains over time.”

Architectures degrade if left unchecked:

  • Teams might take shortcuts.
  • Requirements evolve.
  • Tech changes.

📌 Example: A startup that launched with a monolith may now struggle to scale. A good architect would reassess and refactor toward modularity or microservices.

Architects must observe the decay, and proactively evolve the design.


“The decisions an architect makes tend to be long-lasting and difficult to change.”

That’s why you must:

  • Stay updated on tools like Kubernetes, serverless, observability stacks (e.g., OpenTelemetry).
  • Understand emerging patterns (e.g., event-driven architectures, edge computing).

📌 Example: Adopting containerization early allows easier migration to cloud-native platforms later.


4. Ensure Compliance with Architecture

“Violations can cause ripple effects and undermine the system.”

Architects must:

  • Monitor whether teams are following defined decisions.
  • Use tools like ArchUnit (Java) or fitness functions to enforce structure.

📌 Example: A developer bypasses the service layer to make a DB call from the UI—this violates layering, potentially breaking encapsulation. If the DB schema changes, the UI could crash.


5. Diverse Exposure & Experience

“An architect should be familiar with a variety of technologies.”

Not an expert in all, but enough to:

  • Recognize appropriate use cases.
  • Spot trade-offs.

📌 Example: Knowing that Redis offers speed but lacks persistence helps you choose between Redis and PostgreSQL based on whether you need caching or durable storage.


6. Business Domain Knowledge

“Without business domain knowledge, it is difficult to design an effective architecture.”

You need to:

  • Speak the language of stakeholders.
  • Understand the business goals driving technical choices.

📌 Example: In a fintech app, knowing terms like “hedge ratio” or “margin call” allows you to design a domain-driven architecture with bounded contexts that match business areas.


7. Interpersonal & Leadership Skills

“Architecture is a people problem.”

Architects must:

  • Facilitate decisions across teams.
  • Mentor devs.
  • Communicate ideas clearly.

📌 Example: You’ll need to present the rationale behind a new deployment pipeline to both engineers and business leads, adjusting the message to each audience.


8. Understand and Navigate Politics

“Almost every decision an architect makes will be challenged.”

You must:

  • Anticipate resistance (from devs, managers, stakeholders).
  • Negotiate and persuade.

📌 Example: If you propose data silos to protect customer information, other teams will resist losing direct access. You’ll need to justify it using security, audit, and long-term maintainability arguments.


🔗 The Expanding Scope of Software Architecture

Modern architecture now intersects deeply with:

▶ Engineering Practices

  • CI/CD, automated testing, fitness functions
  • Evolutionary architecture ensures systems adapt gracefully.

📌 Example: Use a test that fails the build if page load times exceed 1.5 seconds. This enforces performance as a “first-class concern.”


▶ DevOps

“DevOps is a revolution, not a buzzword.”

Before DevOps, architects designed around the assumption that ops is slow and bureaucratic.

Now:

  • Architecture and ops are symbiotic.
  • Architects design systems assuming automated provisioning, observability, resilience.

📌 Example: Kubernetes-native apps assume dynamic scaling, circuit breakers, service discovery—this shapes architecture from day one.


▶ Software Development Process

  • Architecture supports Agile better than Waterfall.
  • Why? Agile’s iterative nature matches the way architecture evolves.

📌 Example: You start with a monolith for speed, but incrementally extract services using the Strangler Fig pattern. Agile enables this controlled evolution.


▶ Data

“Code and data have a symbiotic relationship: one isn’t useful without the other.”

Architects must:

  • Understand data ownership, partitioning, and access patterns.
  • Respect data consistency, latency, and governance constraints.

📌 Example: Event sourcing is great for traceability but complicates consistency and querying. Understanding these trade-offs is architectural thinking.


⚖️ The Laws of Software Architecture

First Law: ❝ Everything in software architecture is a trade-off. ❞
Corollary: ❝ If you think it isn’t, you haven’t identified the trade-off yet. ❞

📌 Example:

  • REST APIs: Simple, flexible—but verbose and slower than binary protocols.
  • gRPC: Fast and efficient—but harder to debug and monitor.

Second Law: ❝ Why is more important than how. ❞

Knowing why a decision was made is more valuable than how it was implemented.

📌 Example: A system may use a relational DB over NoSQL. Unless the reasons (e.g., strict ACID compliance, existing talent) are documented, future teams might assume it’s a mistake.

Absolutely! Let’s deep dive into Chapter 2: “Architectural Thinking” from Fundamentals of Software Architecture: An Engineering Approach by Mark Richards and Neal Ford.

This chapter lays the cognitive foundation of how software architects should think—a way of seeing problems, solutions, and systems differently from developers. It breaks down the mindset shift required and explores how architects must balance trade-offs, business needs, and broad technical knowledge.


🧠 What Is Architectural Thinking?

“An architect sees things differently from a developer’s point of view.”

The authors liken this to how a meteorologist sees clouds versus how an artist sees them:

  • The artist sees beauty, form, and expression.
  • The meteorologist sees weather patterns, barometric pressure, and forecasts.

In the same way:

  • Developers see code, classes, bugs, and features.

  • Architects see coupling, scalability, resilience, and trade-offs.

  • architectural thinking is about perspective, not just technical depth. It’s the ability to elevate above code, to recognize patterns, trade-offs, and systems-level implications.

Architectural thinking is not just “thinking about the architecture.” It’s about a holistic and systemic mindset.


🧭 Four Pillars of Architectural Thinking

The chapter explores four major aspects:


1. 🏗 Understanding the Difference Between Architecture and Design

“Architecture and design integrate closely to form solutions to business and technical problems.”

🛠 Traditional View (Flawed):

  • Architects decide high-level things: components, patterns, layers.
  • Developers implement the code and UI.
  • Communication is one-way (architect ➝ developer).

📌 Problem: Architects become disconnected from implementation. Developers change architecture, architects don’t know, and vice versa.

✅ Modern View:

“To make architecture work, both the physical and virtual barriers must be broken.”

  • Architecture and development should be collaborative.
  • Architects and developers must be on the same team.
  • There should be a bidirectional flow of communication.

🔄 Example: If a development team finds that a synchronous call is causing latency spikes, they must work with the architect to adjust toward asynchronous design—not just patch the code quietly.

Thinking like an architect is knowing the difference between architecture and design and seeing how the two integrate.

This distinction can be subtle but critical.

  • Architecture: Focuses on system-wide decisions, such as choosing microservices over a monolith, defining APIs, selecting message buses, etc.
  • Design: Focuses on localized implementation, like writing class hierarchies or designing user forms.

🔥 Example:

Role Activity
Architect Defines modular boundaries, service interfaces, data flow
Developer Implements validation logic, user interface behaviors

A clear example is in choosing an architectural style (like Event-Driven Architecture). That’s an architectural decision. A developer implementing a pub-sub component in JavaScript is doing design.


2. 🌐 Technical Breadth vs. Technical Depth

“An architect must have a significant amount of technical breadth.”

📚 The authors present the Knowledge Pyramid:

  • Stuff You Know: Your current stack (e.g., Java, Spring Boot).
  • Stuff You Know You Don’t Know: Heard of but no expertise (e.g., Rust, GraphQL).
  • Stuff You Don’t Know You Don’t Know: Unknown unknowns (e.g., new paradigms like CRDTs or emerging protocols).

Developers: Focus on deepening the top of the pyramid—expertise in one area.
Architects: Expand the middle layer—breadth of awareness across technologies, paradigms, platforms.

“For an architect, it is more beneficial to know that five solutions exist than to be an expert in only one.”

📌 Real-world example:

  • A developer may master Redis.
  • An architect should know:
    • Redis: In-memory speed, ephemeral.
    • Memcached: Simple key-value store.
    • Hazelcast: Distributed, Java-native.
    • Ehcache: Tight JVM integration.
    • Couchbase: Hybrid NoSQL with caching features.

This way, the architect can choose the right tool depending on system trade-offs.

This is about T-shaped skills:

  • Horizontal bar: Broad exposure to languages, cloud platforms, architecture patterns, databases, etc.
  • Vertical bar: Deep expertise in at least one domain, like performance tuning or cloud deployment.

📌 Examples:

  • An architect might need to compare REST vs. gRPC, but also be able to configure NGINX for reverse proxying.
  • You must know why Kafka is great for event processing and how to deploy a Kafka cluster securely in AWS.

Staying hands-on is key. Architects who code at least semi-regularly have a stronger grasp of what’s practical.


3. ⚖️ Analyzing Trade-Offs

“Everything in architecture is a trade-off.”
“Architecture is the stuff you can’t Google.”

This is the core mental model of architectural thinking.

Architects must constantly weigh:

  • Performance vs. scalability
  • Simplicity vs. extensibility
  • Security vs. usability
  • Flexibility vs. consistency

📦 Example: Auction System Messaging (Queue vs. Topic)

💬 Scenario: A Bid Producer sends data to three services:

  • Option A: Topic (Publish-subscribe)
  • Option B: Queues (Point-to-point)
Topic (pub-sub) Queues (point-to-point)
✅ Easy extensibility (add new services easily) ❌ Adding new services requires code change
✅ High decoupling ❌ Tight coupling (Bid Producer must know all queues)
❌ Shared contract for all subscribers ✅ Custom contracts per service
❌ Hard to detect rogue listeners ✅ Queue consumption is exclusive
❌ No per-service scaling ✅ Each queue can be monitored & scaled

❝Architects must ask: which is more important—extensibility or security and monitoring?❞
❝There are no right or wrong answers in architecture—**only trade-offs.**❞

🧠 The key insight here is that architects must choose intentionally—not based on fads or preferences.

🔄 Examples of Trade-Offs:

  • Microservices vs. Monoliths:
    • Microservices offer scalability and team autonomy.
    • But they introduce latency, distributed data challenges, and devops complexity.
  • SQL vs. NoSQL:
    • SQL provides transactional integrity.
    • NoSQL scales better horizontally, but sacrifices some ACID guarantees.

The ability to reconcile these trade-offs comes with experience, context awareness, and communication with stakeholders.


4. 💼 Understanding Business Drivers

“Without understanding business goals, architects can’t create relevant solutions.”

Architecture must serve the business. It’s not about cool tech; it’s about value delivery.

🧭 Examples:

  • If time-to-market is crucial, favor low-coupling, high-deployability architectures (e.g., modular monoliths or microservices).
  • If compliance (e.g., HIPAA, GDPR) is a top concern, you must architect for data governance and auditing.
  • If the business expects extreme scalability, focus on elastic architectures like serverless or event-driven styles.
  • A real-time trading platform prioritizes latency over fault tolerance.
  • A medical records system prioritizes availability, auditability, and data integrity over speed.

Architects must know:

  • Business strategy (e.g., growth, cost reduction)
  • Critical risks (e.g., compliance, uptime)
  • Market dynamics (e.g., customer needs, regulatory shifts)

This knowledge informs what characteristics are prioritized in the architecture.


🚧 Breaking the Barrier Between Architect and Developer

“We believe every architect should code.”The architect and developer must be on the same virtual team.

But coding can become a bottleneck. So how can architects remain hands-on?

Strategies:

  • Avoid owning critical-path code (delegate to devs).
  • Write code 1–3 sprints ahead (future features, POCs).
  • Own architecture stories (e.g., refactor messaging layer).
  • Fix bugs to stay grounded in real system pain points.
  • Write automation tools (e.g., internal CLIs, config validators).
  • Develop fitness functions for performance, security, structure.
  • Conduct code reviews as an active architectural feedback loop.
  • Architects join daily standups and pair program occasionally.
  • The architect coaches and mentors.
  • Architecture is iterative, not a big upfront design.
  • Decisions are made with feedback from implementation.

📌 Example: An architect writes a fitness function that fails CI if the service has more than 2 synchronous outbound dependencies—enforcing the resilience characteristic.


🧠 Bonus: The Knowledge Triangle

Though not explicitly in Chapter 2’s main body, the knowledge triangle is a related concept discussed in the self-assessment section:

  • Awareness: Knowing a concept exists (e.g., eventual consistency).
  • Understanding: Being able to explain how it works.
  • Skill: Having used it hands-on in a real system.

➕ Architects should aim to:

  • Have awareness of dozens of tools.
  • Have understanding of many patterns.
  • Have skills in a few deeply.

🧊 ⚠ Frozen Caveman Anti-Pattern

“Architects often fear reoccurrences of old problems and over-design for edge cases.”

A humorous but real problem:

  • An architect once had a system go down when Italy’s network failed.
  • Now, every system he designs includes isolated regional failovers—even when not necessary.

🧠 Takeaway: Don’t let past trauma or confirmation bias dictate design.

Quotes

Quote Meaning
“Architecture is the stuff you can’t Google.” Architecture requires context, not recipes.
“Everything in architecture is a trade-off.” There are no perfect solutions.
“Architecture and design must be in sync.” No handoffs—just continuous collaboration.
“Why is more important than how.” Understand the rationale, not just the mechanics.
“An architect must see beyond code—to systems, teams, and outcomes.” Architecture is about scale, impact, and guidance.

References


Profile picture

Written by Tony Vo father, husband, son and software developer Twitter