
What Drew Me In
As a software architect and transformation specialist, I’ve learned that the hardest problems we face are rarely just technical. They sit at the intersection of architecture, engineering practices, and organizational design.
I first came across Fundamentals of Software Architecture: An Engineering Approach by Mark Richards and Neal Ford in 2020, when the first edition was published. At the time, the title itself stood out to me. The phrase engineering approach is what caught my attention.
This book suggested something different from the usual architecture books. It is less about abstract concepts or isolated patterns, and more about treating architecture as a combination of trade-offs which shapes the important things in software.
Architecture is about the important stuff … whatever that is. — Ralph Johnson
Mark Richards is a hands-on software architect, trainer, and published author. he has experience in the architecture and delivery of Microservices Architectures, Service-Based Architectures, and Service-Oriented Architectures in a variety of platforms and languages.
Neal Ford is a software architect, author, and speaker. He is an independent software consultant, specializing in software architecture and modern software engineering practices.
Now, with the release of the second edition in 2025, I found myself coming back to it again. In part because of my curiosity to re-read the original work, and in part because this is a subject that is really part of the day-to-day life of a software architect where architecture is not just about design, but about decision-making.

Key Insights
Fundamentals of Software Architecture: An Engineering Approach starts with an introduction as Chapter 1, followed by three main parts that structure the rest of the content.
In this introduction, the authors, Mark Richards and Neal Ford, begin by defining what software architecture actually means. They describe software architecture as a concept with four key dimensions:
- Architectural style as the starting point
- Architectural characteristics that the system must support
- Logical components that implement the system’s behavior
- Architectural decisions that tie everything together and justify the overall design
This definition sets the foundation for the rest of the book, framing architecture not as a single artifact, but as a combination of structure, qualities, and decisions.
The introduction then continues with an important section: the laws of software architecture.
In the second edition, the authors expand this concept by introducing a third law. While the first edition presented two laws, this version includes three.
- The first law of software architecture states that everything in software architecture is a trade-off.
- The second law emphasizes that “why” is more important than “how”. Which means, for architects, understanding the reasoning behind decisions is critical.
- The third law, newly introduced in this edition, highlights that most architectural decisions are not binary. Instead, they exist on a spectrum between different extremes, requiring careful judgment rather than simple yes/no choices.
The introduction concludes with a section on the expectations of a software architect. The authors explain that the role of a software architect can vary significantly. It can range from acting as a highly experienced programmer to defining the broader technical direction of an entire organization.
This section positions the architect not just as a technical role, but as one that operates across both technology and organization.
💡 Foundations of Software Architecture
The first part of the book focuses on foundational concepts and terminology that every developer and architect should understand. It covers essential topics such as modularity, security, and other “-ilities” that play a key role in software architecture.
👉 Chapter 2 introduces the concept of architecture thinking, which is essentially about seeing systems through an architect’s eyes. The authors explain that from an architectural perspective, you need to look beyond immediate changes and understand how those changes impact the system as a whole, such as scalability, performance, and other architectural characteristics.
The chapter then explores the difference between architecture and design.
- Architecture is less about the appearance of a system and more about its structure.
- Design, on the other hand, focuses more on how the system is implemented and organized at a lower level.
They further distinguish the two by highlighting that:
- Architecture involves significant trade-offs, while design deals with more localized trade-offs
- Architecture decisions require high effort, whereas design decisions typically require less effort
- Architecture is strategic, while design is tactical
Another important concept introduced in this chapter is technical breadth. Unlike developers, who usually need deep expertise in specific areas, software architects must develop a broad understanding across many domains. This breadth allows them to evaluate systems holistically and make informed decisions across different technologies and concerns.
To illustrate this, the authors present a pyramid:
- At the top: things you know
- In the middle: things you know you don’t know
- At the bottom: things you don’t know you don’t know
👉 Chapter 3 focuses on modularity as a fundamental organizing principle in software architecture. An important distinction introduced in this chapter is between modularity and granularity, which are often used interchangeably but represent different concerns.
- Modularity is about how a system is decomposed into smaller units
- Granularity is about the size of those units, how big or small each component or service should be
The key insight is that while modularity defines the structure, granularity defines the scale of that structure; and getting the balance right between the two is essential in architectural design.
Next, the authors focus on how to measure modularity, introducing several key concepts. The first is cohesion, which refers to the degree to which elements within a module belong together. In other words, how well a module is focused on a single responsibility.
The book outlines several types of cohesion, including: functional cohesion, sequential cohesion, communicational cohesion, procedural cohesion, temporal cohesion, logical cohesion and coincidental cohesion.
The second concept is coupling, which describes the level of dependency between modules. While cohesion looks inward, coupling looks outward. Managing coupling is essential to maintain flexibility and reduce the impact of changes across the system.
The chapter concludes with additional ways to evaluate modularity through core metrics and the concept of connascence. Connascence describes different types of dependencies between components and is divided into:
- Static Connascence, which can be analyzed at design or compile time
- Dynamic Connascence, which emerges at runtime
👉 Chapter 4 focuses on architectural characteristics, often referred to as non-functional requirements. However, the authors, Mark Richards and Neal Ford, intentionally use the term architectural characteristics to emphasize their importance in shaping the system.
They explain that while architects may collaborate on defining business or domain requirements, one of their key responsibilities is identifying and defining these architectural characteristics.
The authors describe architectural characteristics using three criteria, represented as a triangle:
- Explicit: specifies non-domain design considerations
- Implicit: influences structural aspects of the system
- Critical: essential for the success of the application
Together, these dimensions help clarify what truly qualifies as an architectural characteristic.
The chapter then presents a categorized (but not exhaustive) list of these characteristics, grouped into four main areas:
- Operational characteristics: such as availability, continuity, performance, and reliability
- Structural characteristics: including configurability, extensibility, and maintainability
- Cloud characteristics: such as zone-based availability and on-demand scalability
- Cross-cutting characteristics: including security, privacy, accessibility, usability, and legal considerations, spanning across all other groups
The chapter concludes with an important perspective on trade-offs. Not all architectural characteristics can be fully optimized at the same time. As a result, architects must continuously balance competing concerns. As the authors emphasize:
Never aim for the best architecture, but rather for the least worst architecture.
This reinforces the idea that architecture is ultimately about making informed compromises.
👉 Chapter 5 focuses on how to identify architectural characteristics, starting from domain concerns.
The authors explain that most architectural characteristics emerge from understanding the needs of key domain stakeholders and collaborating with them. While this might sound straightforward, it requires a critical skill from architects: the ability to extract and translate domain concerns into architectural characteristics.
For example:
- A domain concern like time to market can translate into architectural characteristics such as agility, testability, and deployability
- A concern like user satisfaction may lead to performance, availability, security, and fault tolerance
This translation process is not mechanical—it requires interpretation, experience, and continuous interaction with stakeholders.
The chapter then introduces a structured practice called Kata for extracting architectural characteristics. The idea is to repeatedly practice this translation process, helping architects improve their ability to identify the right characteristics in different scenarios.
Overall, this chapter emphasizes that identifying architectural characteristics is not just about analysis, but about practice and refinement over time.
👉 The rest of Part I continues with chapter 6 and chapter 7 focus on how to measure, govern, and properly scope architectural characteristics. The authors first explain that architectural characteristics must be measurable. They describe different types of measures:
- Operational measures (such as performance and availability)
- Structural measures (such as coupling and modularity)
- Process measures (such as agility, stability, and deployment-related concerns)
The chapter then introduces governance, especially through the concept of fitness functions.
Fitness functions are used to continuously assess whether a system still meets its intended architectural characteristics. They help ensure that architecture is not only defined but also maintained over time.
Building on this, the next chapter introduces the concept of scope through the idea of the architectural quantum. An architectural quantum defines the boundary within which a set of architectural characteristics applies. It is typically characterized by: independent deployability, high functional cohesion, low external static coupling and often synchronous communication within its boundary.
👉 The final chapter of Part 1, chapter 8, focuses on component-based thinking and the role of logical components in software architecture.
Mark Richards and Neal Ford define logical components as the building blocks that represent functionality within a system. They also explain how to identify these components and determine the appropriate level of granularity, primarily by analyzing cohesion.
In practice, logical components are often reflected in structures such as namespaces or directory hierarchies, where the source code for a specific functionality is organized. The chapter then clarifies an important distinction between logical architecture and physical architecture:
- Logical architecture focuses on the system’s components and how they interact with each other
- Physical architecture represents the actual deployment artifacts, such as services, user interfaces, databases, and other infrastructure elements
This distinction helps architects separate concerns between how a system is conceptually organized and how it is physically realized. The chapter continues by exploring component coupling and its different types.
One important type is static coupling, which occurs when components communicate directly—typically through synchronous interactions. In this context, the authors highlight two key metrics that architects should consider:
- Afferent coupling: the degree to which other components depend on a given component
- Efferent coupling: the degree to which a component depends on other components
Another type discussed is temporal coupling, which represents non-static dependencies—usually related to timing, sequencing, or transactional behavior.
The chapter concludes with the Law of Demeter (sometimes referred to as the principle of least knowledge). It states that a component or service should have limited knowledge of other components, interacting only with what is necessary.
💡 Architecture Styles
Part 2 begins with foundational concepts, starting with the distinction between architectural styles and architectural patterns. Mark Richards and Neal Ford explain that an architectural style describes a combination of characteristics, including: Component Topology, Physical Architecture, Deployment Model, Communication Style and Data Topology.
A named style provides a concise way to describe this otherwise complex set of factors. In contrast, architectural patterns represent recurring solutions that have appeared repeatedly throughout the history of software architecture. The book highlights several well-known patterns, such as: Big Ball of Mud, Unitary (monolithic) architecture, Client-server architecture and Three-tier architecture. These patterns reflect how systems have evolved over time as they grow in complexity and capability.
The chapter then moves into a comparison between monolithic and distributed architectures, introducing the well-known fallacies of distributed computing. These include assumptions such as, the network is reliable or latency is zero. These fallacies highlight the hidden complexities and risks involved in distributed systems.
Finally, the chapter concludes with a discussion on team topologies and architecture, emphasizing the relationship between system design and team structure. The authors describe four types of teams: stream-aligned teams, enabling teams, complicated subsystem teams and platform teams.
👉 Layered Architecture
In chapter 10, authors describe the layered architecture as a style where system components are organized into horizontal layers, each responsible for a specific role. Commonly, these include presentation, business, persistence, and database layers. Each layer interacts only with the layer directly below it, creating a clear separation of concerns and a structured flow of responsibilities within the application.
From an architectural characteristics perspective, this style offers high simplicity and clear organization, making it easy to understand and implement. However, its modularity and evolvability are limited due to tight coupling between layers, and changes often propagate across multiple layers. While it supports maintainability and testability to some extent, scalability and elasticity remain constrained, as it is typically implemented as a single deployment unit.
👉 Modular Monolith Architecture
In chapter 11, the authors describe the modular monolith as a monolithic architecture that is structured around business domains rather than technical layers. Even though the system is deployed as a single unit, its internal organization follows a modular approach, where functionality is grouped into cohesive components. These modules are typically reflected in code structures such as namespaces or directories, reinforcing logical boundaries within the monolith.
From their perspective, this architecture style emphasizes simplicity and operational efficiency, since everything runs as a single deployment unit. At the same time, they highlight the trade-offs: while modularity exists at the logical level, scalability, elasticity, and fault isolation remain limited compared to distributed architectures.
👉 Pipeline Architecture
In chapter 12, Mark Richards and Neal Ford describe the pipeline architecture as a composition of filters and pipes, where each filter performs a specific piece of functionality and passes the result to the next stage through a pipe. The communication is typically unidirectional, forming a sequential flow of data processing. While this architecture is often implemented as a single deployment unit, they also point out that it can be extended into a distributed model by deploying filters as separate services.
From an architectural characteristics perspective, this style offers high simplicity and clear separation of processing steps, making it well-suited for scenarios involving sequential transformations. It provides reasonable modularity and maintainability, but its technical partitioning and linear flow limit flexibility in more complex domains. Scalability, elasticity, and fault tolerance are relatively constrained, especially in monolithic implementations.
👉 Microkernel (Plug-in) Architecture
In chapter 13, the authors present the microkernel architecture as a monolithic style built around a core system and plug-in components. The core system provides the essential functionality and infrastructure, while additional features are implemented as independent plug-ins. This separation allows the system to isolate core logic from extensions, enabling customization and adaptability without impacting the central part of the application.
From an architectural characteristics perspective, this style offers strong modularity and extensibility, making it suitable for systems that require frequent feature expansion or user customization. It maintains good maintainability and testability, while still benefiting from the simplicity of a single deployment unit. However, like other monolithic approaches, it has limitations in scalability, elasticity, and fault isolation.
👉 Service-Based Architecture
In this chapter 14, Mark Richards and Neal Ford introduce service-based architecture as a distributed, domain-partitioned style built around coarse-grained services. Each service typically represents a business domain or subdomain and is deployed independently, while a separate user interface interacts with these services. Unlike microservices, these domain services are larger in scope and often share a common database, which simplifies certain aspects of the architecture while still enabling distribution.
They emphasize that this style aims to strike a balance between monolithic simplicity and distributed flexibility. Services are designed to be as independent as possible, but communication between them is usually minimized rather than encouraged.
In practice, this means architects should carefully define domain boundaries and avoid excessive interaction between services. The book also highlights a practical guideline: keeping the number of services limited (often around a dozen) to prevent complexity in areas like deployment, testing, and data management.
From an architectural characteristics perspective, this style provides good modularity, maintainability, and deployability, along with improved scalability compared to monolithic approaches. It also works well in cloud environments, where services can leverage infrastructure capabilities. However, it introduces trade-offs, particularly around data coupling and inter-service communication.
👉 Event-Driven Architecture
In chapter 15, the authors describe event-driven architecture as a style based on asynchronous communication, where components react to events rather than directly invoking each other. The flow typically starts with an initiating event, which is sent to an event broker, processed by one or more event processors, and may generate additional derived events. This creates a chain of reactions, allowing the system to evolve through loosely connected event flows rather than tightly coupled calls.
A key distinction highlighted in this chapter is between events and messages. Events represent something that has already happened, while messages usually indicate something that should happen. This difference reinforces the reactive nature of EDA, where components respond to facts rather than commands. The architecture relies heavily on asynchronous patterns such as fire-and-forget and request/reply, which improves responsiveness from the user’s perspective by decoupling processing from immediate responses.
From an architectural characteristics perspective, EDA offers high scalability, elasticity, and fault tolerance, as components can operate independently and scale based on demand. It also supports strong evolvability due to its loose coupling.
👉 Space-Based Architecture
Chapter 16 introduces space-based architecture as a style designed to address scalability and performance challenges by removing the traditional database bottleneck. It is based on the concept of tuple space, where multiple processing units operate in parallel and communicate through shared in-memory data structures. Instead of relying on a central database for every transaction, data is replicated across these units, allowing the system to handle high load more efficiently.
The authors describe this architecture as consisting of several key components, including processing units that contain application logic and virtualized middleware that coordinates communication and data management. Supporting elements such as messaging grids, data grids, processing grids, and deployment managers work together to manage state, synchronize data, and scale the system dynamically. Data is typically written asynchronously to the database, reducing contention and enabling the system to remain responsive under heavy load.
From an architectural characteristics perspective, this style provides excellent scalability, elasticity, and responsiveness, making it well-suited for high-throughput systems. It also supports strong fault tolerance due to distributed processing and data replication.
👉 Orchestration-Driven Service-Oriented Architecture (SOA)
Mark Richards and Neal Ford describe orchestration-driven SOA as a distributed architecture centered around a structured hierarchy of services, each with clearly defined responsibilities in chapter 16. The architecture typically includes business services, enterprise services, and an integration layer, often implemented using an enterprise service bus (ESB), with an orchestration engine coordinating interactions.
The authors also highlight an important risk: the tendency for the ESB or orchestration layer to grow uncontrollably, leading to what they call the accidental SOA anti-pattern. In such cases, too much logic is centralized, increasing complexity, reducing flexibility, and making the system harder to maintain and evolve.
From an architectural characteristics perspective, this style offers strong scalability, elasticity, and fault tolerance, particularly in large enterprise environments where integration is critical.
👉Microservices Architecture
In chapter 17, authors present microservices as one of the most influential modern architecture styles, shaped both by industry evolution and architectural thinking.
They highlight that, unlike many styles that emerge gradually, microservices were explicitly defined early, largely influenced by Martin Fowler and James Lewis. Furthermore, microservices connect strongly with domain-driven design, particularly the concept of bounded context, which drives the decomposition of systems into small, independent, domain-aligned services.
From a structural perspective, the book emphasizes that microservices are highly distributed and fine-grained, with each service running in its own process and owning its data and dependencies. This eliminates many problems seen in shared infrastructures, such as resource contention and poor isolation. However, this independence introduces complexity in communication. The authors explain that architects must carefully choose between synchronous and asynchronous interactions, and that microservices typically rely on what they call protocol-aware, heterogeneous interoperability.
Finally, the architectural characteristics reflect both the strengths and trade-offs of this style. Microservices score very high in modularity, deployability, testability, andscalability, making them ideal for systems that require rapid evolution and independent deployments.
At the same time, the authors point out the cost of this flexibility: increased operational complexity, higher infrastructure costs, and the need for strong DevOps and automation practices.
💡 Techniques and Soft Skills
To conclude the book, the authors change the emphasis from software architecture styles and technology patterns to another equally important subject: the human side of software architecture. They emphasize that software architecture is not only about making the right decisions, but it is equally about having the right techniques, tools, and human skills to apply them in practice.
👉 In Chapter 21, Mark Richards and Neal Ford talk about making architectural decisions which is one of the most important skills that any architect must master, and these decisions affect not just the structure of the system but also the technology and architectural characteristics that are chosen.
This topic strongly resonated with me, and I previously delved into this topic further in a blog post based on this chapter.
👉 The Fundamentals of Software Architecture: An Engineering Approach book shift the focus from defining architecture to assessing and effectively communicating it. Chapter 22, for instance, discusses the importance of assessing risk in architecture, with a focus on risk assessment matrix and risk storming approaches to assess risks from both structural and operational perspectives. Chapter 23 continues from this perspective, arguing that, in addition to making right decisions, architects also need to communicate them effectively, and hence introduces diagramming.
👉 Chapter 24 focuses on an often overlooked aspect of software architecture: making teams effective. The authors explain that architecture is not just about designing systems but also about enabling teams to successfully implement those designs. Effective architects actively collaborate with developers, provide clear guidance, and avoid working in isolation. The chapter also introduces three common types of architects:
- Effective architect: Strikes the right balance by setting appropriate boundaries, collaborating closely with teams, and enabling developers to succeed.
- Control-freak architect: Overly prescriptive, creates tight constraints, and micromanages decisions, often slowing teams down.
- Armchair architect: Detached from implementation, lacks hands-on experience, and produces overly abstract or impractical designs.
👉 Chapter 25 emphasizes the importance of negotiation and leadership skills in the life of a software architect, who is constantly required to strike a balance between various factors. According to the authors of the book, good architects are not just good designers but are also good at facilitating discussions and helping teams reach a common ground on a feasible solution.
👉 The book ends by bringing everything together through architectural intersections and laws. In Chapter 26, the authors focus on how a successful architecture has to line up not just with its internal design, but also implementation, infrastructure, and operation, stressing how important it is to consider the whole ecosystem in which the system exists. Chapter 27 reviews and discusses the laws of software architecture, reinforcing how every decision is a trade-off, how the reason for a decision is more important than how, and how architectural decisions exist on a spectrum, not a binary choice, leaving the reader with a mindset for balanced decisions.

My Reflections
Reading this book as a senior software architect and transformation expert, I found myself thinking through the balance between theory and the complexity of the real world software products. The part that most relates to my own thinking is the emphasis on trade-offs, as this is something I am constantly exposed to.
The Fundamentals of Software Architecture: An Engineering Approach book is reinforcing my own views, which I think are important, namely that architecture is not about being perfect, but being conscious and understanding the implications.
Another important reflection for me was the manner in which the book defines the various architectural styles presented in the book. Unlike the common perception of these styles being a trend, the book defines them as a response to a challenge. This resonates with my approach to architecture and the selection of the various styles depending on the context of projects and requirements.
Another point that stood out was the relationship between architecture and team topologies. The concept of this relationship between architecture and teams aligns with my experience working on transformation projects. It emphasizes that building systems is not only about components and services but also about ownership, communication, and how teams operate around boundaries.
Finally, the emphasis on soft skills struck a chord with me, being a hands-on architect. The book reaffirms my understanding that technical knowledge is just half the battle, and that communication and leadership skills are just as important.
This is something that I have learned along the way, where the success of architecture is more dependent on the manner in which it is communicated than on the technical merits of the architecture.

Putting It Into Practice
👉 From the point of view of the Developer, this book helps them gain insights into the reasons behind the system being designed the way it is. The book helps to close the gap between implementation and architecture, as it explains concepts related to architectural characteristics, trade-offs, and communication styles, among other things, and helps the developers interpret the system better, especially in the case of distributed systems, as is the case in the microservices world.
👉 From an architectural point of view, this book can be considered a toolkit for thinking and decision-making. It helps to refine thinking in terms of evaluating trade-offs, selecting suitable architectural styles, and aligning decisions with business and operating objectives. It also helps to reinforce thinking in terms of boundaries, architectural characteristics, and maintaining a holistic approach.
👉 The book offers a good foundation for evaluation and evolution, especially in transformation initiatives. It helps to identify mismatches between architectures and organizational requirements, risks, and structural limitations, and is useful for decision-making when shifting architectural styles. It also helps to bring clarity to the evolution required for systems, teams, and processes, making it easier to reason about transformation.
👉 For tech leads, it provides valuable guidance on how to relate architecture to day-to-day work. It helps in effective communication between various teams and stakeholders, facilitates effective communication of architectural decisions to guide action, and reinforces leadership in navigating complexity. It also emphasizes the importance of finding a balance between collaboration and providing technical direction, enabling teams to work together while maintaining autonomy.

The Verdict
This Fundamentals of Software Architecture: An Engineering Approach is, in my view, one of the most well-rounded resources for anyone navigating the path toward software architecture or already working within it:
- Ideal for developers transitioning to architects: It builds the right mindset, not just knowledge.
- Highly valuable for hands-on architects: Especially those balancing design, coding, and decision-making.
- Excellent for establishing a shared architectural language or ubiquitous languages: Helping bridge the gap between technical depth and architectural thinking.
- Strong foundation for experienced engineers: who want to better understand trade-offs, styles, and system design at scale.
At the same time, the book stands out for its balance, as it does not promote a particular paradigm or trend, but rather offers a way of thinking.

Complementary Resources
If you’re looking to explore Software Architecture and related topics more deeply, I recommend:
- Youtube Channel: Software Architecture Monday
- Book: Software Architecture: The Hard Parts: Modern Tradeoff Analysis for Distributed Architectures
- Book: Head First Software Architecture: A Learner’s Guide to Architectural Thinking



