Unit 5: Architecture & Design
Learning Objectives
- Describe and compare major architectural styles including layered, microservices, and event-driven architectures
- Evaluate the trade-offs between architectural choices using quality attributes as criteria
- Explain technical debt at the architectural level and its long-term consequences
- Produce an Architectural Decision Record documenting a design choice with alternatives and trade-offs
Core Input
Read through each tab before working through the key concepts.
Software architecture defines the high-level structure of a system — the major components, their responsibilities, and the way they communicate. Architectural decisions are the most consequential in the SDLC: they are made early, constrain everything that follows, and are expensive to reverse.
Layered (N-tier) architecture
Organises the system into horizontal layers, each with a defined responsibility, where each layer depends only on the layer below it. Common layers: presentation, business logic, data access, and persistence. Simple to understand and implement; good separation of concerns. Weakness: can lead to performance overhead from inter-layer calls, and the data access layer becomes a bottleneck in high-throughput systems.
Microservices
Decomposes the system into small, independently deployable services, each responsible for a single business capability and communicating over lightweight protocols (typically HTTP/REST or messaging queues). Advantages: independent deployment, technology flexibility, fault isolation, and horizontal scalability. Disadvantages: distributed systems complexity, network latency, data consistency challenges, and significant operational overhead. Microservices are not inherently superior to a monolith — they introduce costs that are only justified at sufficient scale and team size.
Event-driven architecture
Components communicate by producing and consuming events via a message broker (e.g. Kafka, RabbitMQ). Producers publish events without knowing who consumes them; consumers react independently. Advantages: loose coupling, high scalability, and natural fit for asynchronous workflows. Disadvantages: eventual consistency, difficult debugging, and complex event schema governance.
Every architectural decision involves trade-offs across quality attributes. No architecture maximises all attributes simultaneously — choosing one often requires accepting a cost on another.
Key quality attributes at the architectural level:
- Scalability — can the system handle more load without architectural change? Microservices support horizontal scaling of individual services; a monolith scales as a whole unit.
- Maintainability — how easily can components be changed independently? Low coupling between components reduces the blast radius of any single change.
- Reliability — how does the system behave under partial failure? A microservices architecture with circuit breakers can tolerate the failure of individual services; a tightly coupled monolith may fail as a whole.
- Performance — inter-service communication adds latency. A monolith's in-process calls are faster than a microservice's network calls.
- Deployability — how quickly and safely can changes be released? Microservices enable independent deployment of individual capabilities; a monolith requires full redeployment for any change.
- Simplicity — often undervalued. A simpler architecture is easier to understand, debug, and hand over to new team members.
Architectural technical debt is the accumulated cost of architectural decisions that were expedient at the time but that now constrain the system's ability to evolve. Unlike code-level technical debt (duplicated functions, missing tests), architectural debt is structural and often very expensive to resolve.
Common architectural debt patterns:
- A monolith that was never designed to be decomposed, now impossible to scale or maintain independently
- A layered architecture whose layers have been bypassed — upper layers directly accessing the database
- Missing separation between concerns — business logic embedded in the UI layer
- Synchronous dependencies that cannot tolerate the failure of any component
An Architectural Decision Record (ADR) is a short document that captures a significant architectural decision: the context, the options considered, the decision made, the rationale, and the trade-offs accepted. ADRs prevent two recurring problems: future teams revisiting decisions already made without knowing why they were made, and teams being unable to justify why the system is structured as it is. ADRs are typically stored in version control alongside the code.
Key Concepts: Architectural Styles
Architectural style selection is one of the most consequential decisions in the SDLC. Work through these items with that weight in mind.
The monolith has a poor reputation in contemporary discourse, but this often reflects the success bias of large-scale systems that needed to decompose — not a universal truth. A monolith is often the right choice when:
- The team is small and distributed systems complexity would overwhelm it
- The domain is not yet well understood — decomposing too early creates wrong service boundaries that are expensive to change
- The system does not require independent scaling of components
- Operational simplicity is a priority — one deployment artefact, one log stream, one database
The "modular monolith" — a monolith with well-defined internal boundaries and clean module interfaces — is increasingly recommended as a starting architecture that can evolve into microservices if and when scale demands it.
Microservices are frequently adopted for their benefits without adequate assessment of their costs:
- Distributed systems complexity — network partitions, partial failures, and latency are now first-class concerns. Every inter-service call can fail.
- Data consistency — each service owns its own data store; cross-service transactions require eventual consistency patterns (sagas, event sourcing) that are complex to implement correctly.
- Operational overhead — each service requires its own deployment pipeline, monitoring, logging, and scaling configuration.
- Service coordination — a workflow that spans multiple services must be orchestrated or choreographed; this logic must live somewhere.
The rule of thumb: adopt microservices when the cost of a monolith (inability to scale specific components, deployment coupling, team coordination overhead) exceeds the cost of microservices. For most systems below a certain scale, this crossover never arrives.
Coupling and cohesion apply equally to architecture as to class design:
High cohesion at the architectural level means each component has a clear, single responsibility — one service manages appointment scheduling; another manages patient records; another handles notifications. A component that does many things is an architectural god class.
Low coupling means components can be changed, replaced, or scaled independently without forcing changes in other components. Coupling at the architectural level manifests as: shared databases (two services reading and writing the same tables), synchronous call chains (A calls B calls C calls D — failure in D cascades to A), and shared libraries that evolve in lock-step.
The goal is the same as at the class level: components that can be understood, changed, and deployed independently.
Key Concepts: Decisions and Debt
Architectural decisions persist. These concepts address how to make and record them responsibly.
Architectural technical debt is structural — it is embedded in the shape of the system, not in individual lines of code. This makes it qualitatively different from code-level debt:
- Refactoring a class is a local change. Decomposing a monolith into services affects every team, every deployment pipeline, and every integration point.
- Architectural debt is often invisible until the system needs to grow or change in a way the architecture does not support.
- The longer it accumulates, the more the organisation builds processes around it — making it even harder to change.
The NHS NPfIT programme is a case study in accumulated architectural debt at scale: a centralised architecture that could not accommodate regional variation, combined with a procurement model that locked in vendors before requirements were understood. By the time the debt was recognised, the cost of addressing it exceeded the cost of abandonment.
A minimal ADR has five sections:
- Context — what is the situation? What constraints, requirements, and forces led to this decision?
- Options considered — what alternatives were evaluated? Each option should be listed with a brief assessment.
- Decision — what was chosen?
- Rationale — why was this option chosen over the alternatives? Which quality attributes does it support?
- Consequences — what are the trade-offs accepted? What will be harder as a result of this decision? What will be easier?
The consequences section is critical — and most often omitted. An ADR that does not acknowledge the costs of its decision is rationalisation, not engineering judgement.
Non-functional requirements are not addressed in individual features — they are addressed by the architecture. An NFR requiring 99.9% availability cannot be met by writing careful application code; it requires an architecture with redundancy, failover, and health monitoring built in.
This means that NFRs must be known and understood before the architecture is designed. A team that discovers a latency NFR (e.g. "responses within 500ms") after adopting a synchronous microservices architecture with five inter-service hops may find the NFR cannot be met without architectural redesign.
Each NFR from the requirements baseline should map to specific architectural decisions in the ADR. If an NFR has no corresponding architectural decision, it has not been addressed.
Watch
Video coming soon
Check Your Understanding
Select the best answer for each question.
A system uses a layered architecture where upper layers have begun directly accessing the database, bypassing the data access layer. This is an example of:
An Architectural Decision Record (ADR) that lists only the chosen option and its benefits, without discussing alternatives or trade-offs, is best described as:
AI tools can suggest architectural patterns, generate candidate ADR structures, and even analyse a described system to identify potential coupling concerns.
- Assist: Given a system description and a set of NFRs, AI can propose relevant architectural patterns, draft an initial ADR structure, and identify common architectural anti-patterns to watch for — useful as a checklist and starting point.
- Risk: Architectural decisions carry long-term consequences that extend well beyond the information available at design time. AI cannot weigh organisational culture, team skill level, the true cost of long-term operational overhead, or the specific constraints of a legacy integration. An AI-suggested architecture may be technically coherent but contextually wrong.
- Principle: Architecture is a commitment, not a suggestion. AI can surface options and identify known patterns; only the engineering team — who will live with the consequences — can evaluate trade-offs in context. The ADR should document that evaluation, not an AI's output. Future engineers will need to understand the reasoning, not the recommendation.
Activities
Individual task
Sketch two alternative high-level architectures for the hospital appointment booking system:
- Architecture A: a layered monolith (presentation, business logic, data access layers)
- Architecture B: a services-based approach (at least three named services with defined responsibilities)
For each architecture, list three trade-offs it makes — qualities it supports well and qualities it sacrifices. Reference the NFRs from your Unit 3 requirements baseline. Which of your NFRs does each architecture support? Which does it make harder to achieve?
Pair task
Exchange your architecture sketches with a partner and evaluate each using at least two quality attributes from Unit 1:
- Does the architecture address the availability and performance NFRs from the requirements baseline?
- Is there any evidence of architectural technical debt in either design — bypassed layers, shared state, or synchronous chains that create single points of failure?
- Is either architecture likely to support the methodology the group chose in Unit 2?
Identify the stronger architecture and justify your selection with specific reference to the quality attributes it supports.
Group task — architecture decision for the case study
As a group, agree on an architectural approach for the hospital appointment booking system. Document your decision as a formal ADR with all five sections: Context, Options Considered, Decision, Rationale, Consequences.
The Consequences section must include at least two things this architecture makes harder — not only what it makes easier. Keep this ADR — you will revisit it in Unit 10 and evaluate whether you would make the same decision knowing what you know then.
Update your RTM from Unit 3 to add a column for the architectural component that addresses each requirement.
Review
- Monolith advantages: operational simplicity, in-process performance, easier debugging, lower initial complexity
- Monolith disadvantages: deployment coupling, scaling as a whole unit, potential for tight internal coupling over time
- Microservices advantages: independent deployment, fault isolation, horizontal scaling per service, technology flexibility
- Microservices disadvantages: distributed systems complexity, data consistency challenges, operational overhead, latency from inter-service calls
Neither is universally superior — the right choice depends on the specific quality attributes required and the team's capacity to manage the associated complexity.
An ADR that only documents the rationale for a decision records what the team believed at the time. The Consequences section records what costs and risks were accepted. This serves two purposes: it prevents future engineers from inadvertently reversing a decision whose costs were already paid, and it enables honest retrospective evaluation — did the predicted consequences materialise, and were the predicted benefits realised?
An ADR without consequences is a justification. An ADR with consequences is an engineering record.
Proceed to Unit 6: UML & Documentation when ready.