What Is Software Architecture? Patterns, Principles and Examples
· updated

Every piece of software has an architecture, whether anyone chose it or not. The difference between a system that’s easy to change, scale and keep running and one that fights every change is mostly a handful of decisions made early: how it’s split up, how the parts talk, where the data lives, what happens when something fails. Software architecture is the discipline of making those decisions on purpose. This page covers what it is, what it’s for, the quality attributes it balances, the ten patterns you’ll meet most, the principles behind good decisions, how architecture gets documented, and what the architect role actually involves.
The short answer: Software architecture is the set of structural decisions about a system that are expensive to change later: what the major components are, how they communicate, how data is stored and flows, and how the system achieves the qualities it needs (scalability, reliability, security, performance, maintainability, cost). It sits above design (how components are built internally) and is driven by trade-offs between those qualities, because no architecture maximises all of them. The common patterns, monolith, layered, microservices, event-driven, serverless, hexagonal, CQRS, each favour some qualities at the expense of others. Good architecture is the simplest structure that meets the actual requirements, with the important decisions made explicit and written down.
What software architecture is
The most useful definition: architecture is the set of decisions that are hard to change. Choosing a programming language for a service, splitting a system into services, picking a database, deciding that components communicate through events rather than direct calls, deciding where authentication happens: each of these shapes everything built afterwards, and reversing any of them costs months. Those are architectural decisions. How a particular class is structured is not; you can rewrite it on Tuesday.
That definition explains the discipline’s habits. Architects think about trade-offs rather than best practices, because the decisions have consequences in several directions at once. They document decisions and the reasons for them, because the reasons are what the next team needs. And they try to defer decisions until the last responsible moment, because a decision made with more information is a better decision.
Architecture vs. design
| Architecture | Design | |
|---|---|---|
| Scope | The whole system and its major parts | Inside a component or module |
| Typical decisions | Monolith or services; sync or async; which database; how components communicate; where security is enforced | Classes and interfaces; design patterns; data structures; module layout |
| Cost to reverse | High: weeks to months | Low: hours to days |
| Who decides | Architects, tech leads, senior engineers, with the team | The engineers building the component |
| Artefacts | Diagrams, decision records, interface contracts | Code, class diagrams, code review |
The boundary moves with the system’s size. In a small app, the choice of web framework is architectural; in a large one, it’s a per-service design decision. The test is always cost of reversal.
What architecture is for: quality attributes
Functional requirements say what the system does. Architecture is mostly about the non-functional requirements, usually called quality attributes, and about the trade-offs between them:
- Scalability: can it handle ten times the load, and how: more machines, bigger machines, or not at all?
- Performance: latency and throughput under normal conditions.
- Reliability and availability: how often it fails, how badly, and how it recovers. Expressed as uptime targets and recovery objectives.
- Security: authentication, authorisation, data protection, attack surface.
- Maintainability: how hard it is to change safely. The attribute most often sacrificed and most often regretted.
- Testability: can the parts be tested in isolation?
- Deployability: how often and how safely can it be released?
- Observability: can you tell what it’s doing and why it failed?
- Cost: infrastructure, licensing, and the people needed to run it.
- Portability and interoperability: can it move, and can it talk to other systems?
No architecture maximises all of these. Microservices buy independent scaling and deployability at the cost of operational complexity and latency between services. A single database buys consistency and simplicity at the cost of a scaling ceiling. Caching buys performance at the cost of staleness. Architecture is choosing which trade-offs to make for this system, and the first job on any project is finding out which attributes actually matter. A system for 200 internal users has different priorities from one for 20 million.
The common patterns
1. Layered (n-tier)
The system is organised in horizontal layers, each talking only to the one below: presentation, business logic, data access, database. The default for most business applications for decades, and still the internal structure of most components.
Favours: simplicity, separation of concerns, testability of each layer. Costs: can become a “big ball of mud” if layers leak; every change touches every layer; scales as one unit.
2. Monolith
The whole application is one deployable unit: one codebase, one process (or several copies of it), usually one database. Not a dirty word; most successful systems started as one.
Favours: simplicity, easy local development, transactions across the whole system, low operational cost. Costs: everything scales together; a large team steps on itself; a bad module can’t be isolated.
3. Modular monolith
A monolith with strict internal boundaries: modules with explicit interfaces, no reaching into each other’s tables, often enforced by tooling. Gets most of the organisational benefit of services with none of the network.
Favours: maintainability, team autonomy within a single deployable, a clean path to extracting services later. Costs: discipline to keep the boundaries; still one deployment and one scaling unit. The recommended starting point for most new systems.
4. Microservices
The system is many small, independently deployable services, each owning its data and communicating over the network (HTTP, gRPC, messages). Each service can be scaled, deployed and rewritten separately.
Favours: independent scaling and deployment, team autonomy, technology freedom per service, fault isolation. Costs: operational complexity (service discovery, observability, deployment pipelines for each), network latency and failure between services, no cross-service transactions, hard-to-debug distributed problems. Worth it at a scale of teams and load that most systems never reach.
5. Client-server
A client (browser, mobile app, desktop app) talks to a server that holds the data and logic. The shape of almost every web and mobile application, and usually combined with one of the other patterns on the server side.
6. Event-driven
Components communicate by publishing and consuming events through a broker (Kafka, RabbitMQ, a cloud queue) rather than calling each other directly. An order-placed event is consumed by inventory, billing and email independently.
Favours: loose coupling, resilience (a slow consumer doesn’t block the producer), easy addition of new consumers, natural audit trail. Costs: eventual consistency, harder to reason about flow, duplicate and out-of-order delivery to handle, debugging across events.
7. Serverless
Logic runs as functions triggered by events (HTTP requests, queue messages, file uploads), on infrastructure the cloud provider manages and scales automatically. You pay per invocation.
Favours: zero operations, automatic scaling, cost proportional to use for spiky or low workloads. Costs: cold starts, execution limits, vendor lock-in, and cost that can exceed servers at sustained high load. Good for glue, APIs with variable traffic, and event processing.
8. Model-view-controller and its variants
Separates data (model), presentation (view) and input handling (controller) within an application, usually a UI. Variants: MVP, MVVM. More a design pattern for the presentation layer than a system architecture, but it’s the most-cited pattern in interviews and worth knowing.
9. Hexagonal, clean and onion architecture
Three names for one idea: the business logic sits at the centre with no dependencies on the outside world; databases, UIs, APIs and external services are adapters plugged into ports at the edge. The domain doesn’t know whether it’s talking to Postgres or a test double.
Favours: testability, swappable infrastructure, a domain model that survives framework changes. Costs: more indirection and boilerplate than a small app needs.
10. CQRS and event sourcing
Command Query Responsibility Segregation splits the write model (commands that change state) from the read model (queries optimised for display), often with different data stores. Event sourcing stores the sequence of events that happened rather than the current state, and rebuilds state by replaying them.
Favours: independent scaling of reads and writes, read models shaped for each screen, a complete history. Costs: complexity, eventual consistency between models, and event sourcing is a commitment that’s hard to walk back. Use for domains where history and audit are the point.
Choosing a pattern
| If the priority is | Lean toward |
|---|---|
| Getting to market with a small team | Modular monolith, layered inside |
| Independent scaling of parts with different load | Microservices, or extract one service from a monolith |
| Loose coupling and adding consumers over time | Event-driven |
| Spiky or low traffic with no ops team | Serverless |
| A domain that must outlive its frameworks | Hexagonal / clean at the core |
| Very different read and write loads, or audit history | CQRS, possibly with event sourcing |
| Many teams shipping independently | Microservices with clear ownership |
The honest default: a modular monolith with clean internal boundaries, an event bus where decoupling is needed, and services extracted only when a module has a proven reason to be separate. Most systems that start with microservices spend their first year on infrastructure instead of product.
Principles behind good decisions
- Separation of concerns. Each part does one kind of thing. The UI doesn’t do business logic; the business logic doesn’t know about HTTP.
- Loose coupling, high cohesion. Parts depend on each other as little as possible and each part’s contents belong together. The property that makes change cheap.
- Single responsibility, at the component level. A service or module has one reason to change.
- Design for failure. Every network call can fail, every dependency can be slow, every machine can die. Timeouts, retries with backoff, circuit breakers, graceful degradation, idempotent operations.
- The simplest architecture that meets the requirements. Complexity is a cost paid every day; add it only for a quality attribute you actually need.
- Defer decisions to the last responsible moment. The more you know, the better the decision. Keep options open where it’s cheap to.
- Make the important decisions explicit. Written down, with the alternatives considered and the reasons. See documentation below.
- Evolve rather than rewrite. Architecture changes incrementally; the big rewrite almost never ships.
- Conway’s law. Systems mirror the communication structure of the organisation that builds them. Design the team boundaries and the system boundaries together.
Documenting architecture
The two lightweight practices that most teams find worth the effort:
- C4 diagrams: four zoom levels. Context (the system and what it talks to), Containers (the deployable units: apps, services, databases), Components (the parts inside a container), and Code (rarely drawn). Most teams draw the first two and keep them current.
- Architecture decision records (ADRs): a short document per significant decision: context, options considered, the decision, the consequences. Stored with the code. Two years later, when someone asks “why do we use Kafka here”, the answer exists.
Long architecture documents that nobody updates are worse than none; a current context diagram and a folder of ADRs is enough for most systems.
Architecture in the age of AI tools
AI coding tools have made writing code fast and cheap. They haven’t made architecture cheap: the tools build whatever structure they’re pointed at, and a system built without deliberate boundaries becomes tangled faster than ever, because the code arrives faster. Architecture is now the higher-leverage skill: deciding the boundaries, the contracts and the trade-offs, then directing the tools within them. How to get started with vibe coding covers the beginner’s side; the architectural discipline on this page is what separates a prototype from a system.
The architect role, and how to get there
At most companies “architect” is less a title than a responsibility that senior engineers and tech leads carry. Where it’s a title (solutions architect, enterprise architect, principal engineer), the job is:
- Owning the system-level decisions and their documentation.
- Reviewing designs from teams for consistency with the whole.
- Reasoning about quality attributes and trade-offs with product and leadership, in their language.
- Setting standards: how services talk, how data is owned, how failures are handled.
- Staying close enough to the code to remain credible and correct.
Getting there: design a service and document why. Then a subsystem. Then propose and defend a system-level change. Learn the patterns above well enough to argue against each one. Practise system design interviews, which are the formal test: given a problem, ask about the quality attributes, propose a structure, walk through the trade-offs, and handle the follow-ups about scale and failure. And write. Architecture is mostly explanation.
Where Tailr fits
Roles with architecture in them describe it in their own vocabulary: “system design”, “microservices”, “event-driven”, “distributed systems”, “scalability”, “technical leadership”. A resume that uses the listing’s terms for the systems you’ve actually designed, with the scale and the outcome attached, is the one that gets the system design interview. Tailr tailors your resume to the specific listing you’re viewing, so the architectural decisions and systems that role asks for are the ones your resume leads with, and generates a matching cover letter. For the roles this leads to, what does an AI engineer do and what is a forward deployed engineer both sit on this foundation. Try Tailr on the next senior engineering listing you open.
Conclusion
Software architecture is the set of decisions that are hard to change: how a system is divided, how the parts communicate, where data lives, and how it achieves the qualities it actually needs. It’s driven by trade-offs, because no structure gives you everything, and the patterns, from monolith to microservices to event-driven to hexagonal, are named ways of making particular trade-offs. Choose the simplest architecture that meets the real requirements, write down the important decisions and why, design for failure, and evolve rather than rewrite. That’s the discipline, and it’s the one that matters more, not less, as writing code gets easier.
Frequently asked questions
01What is software architecture in simple terms?
Software architecture is the set of high-level decisions about how a system is structured: what the major parts are, how they communicate, where data lives, and how the whole thing handles scale, failure, security and change. They're the decisions that are expensive to reverse later, which is why they're made deliberately and early. Everything below that level, how a class is designed, how a function is written, is design and implementation.
02What is the difference between software architecture and software design?
Architecture is the structure of the whole system and the decisions that are hard to change: monolith or services, synchronous or event-driven, which database, how components talk. Design is the structure inside a component: classes, interfaces, patterns like factory or observer, how a module is organised. Architecture constrains design; design fills in the architecture. The boundary is fuzzy and the useful test is how costly a decision is to reverse.
03What are the most common software architecture patterns?
Layered (n-tier), monolith and modular monolith, microservices, client-server, event-driven, serverless, model-view-controller and its variants, hexagonal or clean architecture, CQRS with event sourcing, and pipeline or batch architectures. Most real systems combine several: a modular monolith with an event bus, or microservices where each service is internally layered.
04Monolith or microservices: which should I choose?
Start with a modular monolith unless you have a specific reason not to. A single deployable with well-separated modules gives most of the maintainability of services with none of the operational cost. Move a module to a service when it has a genuinely different scaling profile, release cadence or team, and when you have the infrastructure to run and observe many services. Most teams that start with microservices spend the first year on plumbing.
05What are the main principles of software architecture?
Separation of concerns, loose coupling and high cohesion, single responsibility at the component level, designing for failure, keeping the simplest architecture that meets the requirements, deferring decisions until you have information, making the important decisions explicit and recorded, and choosing patterns for the quality attributes you actually need rather than the ones that sound impressive.
06How do I become a software architect?
Most architects are senior engineers who took increasing ownership of system-level decisions: a service, then a subsystem, then the whole system, writing down why each time. The skills to build are breadth across patterns, the ability to reason about trade-offs, communication (architecture is mostly explaining and persuading), and enough depth to stay credible with the engineers implementing it. System design interviews are the formal test; documented decisions on real systems are the evidence.