Software architecture is the small set of structural decisions that shape how safely a system can change. The useful work is not producing a perfect diagram. It is making important trade-offs visible before they harden into cost and risk.
01
Architecture is the part of the design that carries consequences
The phrase software architecture can make a straightforward business application sound like a railway terminal. Somebody draws boxes, chooses serious sounding labels and presents a future in which every part has its own service, database and deployment pipeline.
That is not the useful definition.
Architecture is the part of a system's design that deserves extra attention because getting it wrong would create expensive consequences. It includes the boundaries between parts of the application, where important data belongs, how permissions are enforced, how external systems connect and what must happen when something fails.
Martin Fowler describes architecture as the important parts of a software system and the shared understanding expert developers have about them. He also stresses that good architecture should support its own evolution. Those ideas matter because a system is not finished when the first release goes live. It will meet new users, new rules, new integrations and new commercial demands.
The test is not whether the diagram looks impressive. It is whether the design helps the business make changes without turning every request into an investigation.
02
Start with the business qualities the system must protect
Imagine a growing service business replacing several spreadsheets with one web portal. Staff need to manage customers, collect documents, track cases, calculate charges and send updates. Customers need a secure place to see progress and provide information. Finance wants reliable reporting and the directors want the system to remain useful as the company grows.
The team could start by debating Laravel versus another framework, a monolith versus microservices or one database versus several. Those decisions have no useful context yet.
Start with the qualities the business needs the software to protect:
- Security: customers must only see their own information and staff permissions must reflect real responsibilities.
- Reliability: a failed integration must not silently lose a document or leave a case in an impossible state.
- Changeability: a new service, workflow or rule should not require edits across the entire application.
- Supportability: somebody investigating a problem needs useful logs, history and ownership rather than guesswork.
- Performance: important journeys must remain responsive at the expected load.
- Recoverability: the business needs a tested route back from data loss, a failed release or a supplier outage.
Microsoft's current architecture guidance makes the same connection between technical design and business needs. Reliability, operations, scale and evolution are not abstract engineering goals. They need to match the organisation's risk tolerance, service commitments and ability to operate the result.
If a system is used by twelve people during office hours, it may not need the same availability design as a national payment platform. It still needs permissions, backups and visible failures. Architecture should be proportionate, not absent.
03
Draw the boundaries around the work, not the technology
The example portal has several recognisable areas: customers, cases, documents, billing, communications and reporting. Those are better starting points for boundaries than controllers, database tables or whichever cloud services happen to be fashionable.
A useful boundary contains rules that change for the same business reason. Customer identity and contact details belong together. Case review and approval rules belong together. Billing calculations and invoice state belong together. The user interface can move through all of them, but that does not mean their logic should be mixed into one large controller.
Good boundaries reduce the amount a developer must understand before making a change. Adding a new document requirement should mainly affect the document and case areas. Changing a charge calculation should not risk customer permissions. Replacing an email provider should not rewrite the case workflow.
This is where architecture becomes practical. It gives the team a place for each rule and a clear route between areas. The code is easier to navigate, tests can focus on meaningful behaviour and future separation remains possible if the business genuinely needs it.
04
A monolith is not the same as a muddle
Microservices are often treated as the mature architecture and a monolith as the thing a team must eventually escape. That is a poor starting assumption.
A well structured monolith can have clear modules, one straightforward deployment and a simple operating model. For a small or medium team building a connected business application, that is often a strong choice. Transactions are easier to reason about, local development is simpler and the team does not need distributed tracing, service discovery or a plan for partial network failure on day one.
Microservices can be valuable when different capabilities need genuinely independent deployment, scaling, technology or ownership. They can also help a larger organisation align services with separate teams. The benefits come with a premium: more infrastructure, more interfaces, weaker cross-service consistency and more ways for an ordinary request to fail.
Fowler's review of microservice trade-offs makes the important point that the same characteristic can be a benefit in one context and a burden in another. Strong service boundaries may help a complex organisation. They may slow a small team building a simple application.
The sensible default is not always a monolith and never microservices. It is the simplest architecture that protects today's important qualities while leaving credible seams for tomorrow.
05
Make data ownership explicit
The database often reveals whether boundaries are real.
If every part of the application can update every table, a neat diagram will not prevent accidental coupling. A reporting job may start correcting live case data. A customer import may overwrite fields owned by finance. An integration may become the only place that understands the meaning of a status.
For each important record, decide which part of the system owns its rules and changes. Other parts may read that information or request a change through a defined interface, but ownership should not be ambiguous.
In the portal, the case module might own case status, review decisions and assignment. The billing module owns charges, invoice references and payment state. Reporting can read approved views from both without becoming a second place where business rules are implemented.
This does not require a separate database for every module. It requires discipline about who is allowed to change what. Physical separation can follow later if load, security or team ownership provides a real reason.
Data design also needs an exit route. Record identifiers should not depend entirely on a supplier. Important events should be retained. Imports and exports should be tested. Backups should be restorable. A system that technically owns its data but cannot move or recover it does not have much control.
06
Treat integrations as unreliable by default
External APIs, payment providers, email platforms and finance systems will sometimes be slow, unavailable or surprising. Architecture should make that boring rather than catastrophic.
An important workflow should not lose work because a supplier timed out. Store the intent, attempt the action, record the response and make failures visible to the right person. Retry only when the action is safe to repeat. Use unique event identifiers or idempotency controls where duplicate requests could create duplicate invoices, messages or payments.
Keep provider specific code behind a narrow boundary. The case workflow should ask for a customer notification to be sent. It should not know every detail of the email supplier's API. That reduces the impact of an API change and gives the system a place to record delivery state consistently.
Architecture cannot make an external service reliable. It can stop that service from deciding whether the rest of the business has a coherent record of what happened.
07
Architecture decisions should be evidence, not taste
The most important design choices should connect to a constraint, risk or expected change. A decision made because it is modern is difficult to defend and even harder to revisit.
| Decision area | Question to answer | Evidence worth bringing | Warning sign |
|---|---|---|---|
| Module boundaries | Which rules change together? | Workflow maps, ownership and change history | Boundaries copied from database tables |
| Data ownership | Which part can change each important record? | Audit needs, reporting rules and integrations | Several modules write the same fields |
| Deployment shape | What needs independent release or scale? | Team structure, load and release constraints | Microservices chosen as a maturity badge |
| Integration style | What happens when the supplier is unavailable? | Failure modes, retry rules and support process | A timeout can lose the business action |
| Security | Where must identity, roles and sensitive data be enforced? | User groups, data classification and legal duties | Permissions exist only in the interface |
| Operations | How will a failure be detected and diagnosed? | Service expectations and support ownership | Logs exist but nobody receives an alert |
| Recovery | How much data and downtime can the business tolerate? | Recovery objectives, backup tests and manual fallback | A backup exists but has never been restored |
This table is more useful than choosing a pattern first. It turns architecture into a conversation about consequences. Different answers can lead to different designs without one team being technically inferior.
08
Keep a short record of why
Architecture decisions outlive the meeting in which they were made. Six months later, a developer sees a queue, an unusual identifier or a restriction between modules and wonders whether it is essential or accidental.
Without context, the team can blindly preserve a decision that no longer fits or remove a protection it does not understand.
An architecture decision record, often shortened to ADR, gives the decision a small durable home. Michael Nygard's original format is deliberately lightweight. Record the context, the decision, its status and the consequences. Keep old records when a decision is replaced so the history remains understandable.
For the portal, one record might say:
- Context: document uploads must survive antivirus checks and an unreliable third party storage connection.
- Decision: store the upload request and process it through a queue with explicit states.
- Consequences: the user may see a short processing period, but failures are recoverable and visible.
- Status: accepted, with a review if daily volume exceeds an agreed threshold.
That is enough. An ADR should help the next person understand the trade-off, not become a novel nobody maintains.
09
Use diagrams to create shared understanding
A diagram is valuable when it answers a question for a particular audience.
A system context diagram can show the portal, its users and the external systems around it. A container level view can show the web application, background worker, database and file storage. A focused dynamic diagram can explain how a document moves from upload to review. Those views are more useful than one enormous picture containing every class and connection.
The C4 model provides a simple hierarchy for these views: software system, container, component and code. The useful principle is not the name of the notation. It is choosing the right level of detail and making every box, line and boundary understandable.
Keep diagrams close to the code or operating documentation, give them an owner and update them when an important boundary changes. A stale diagram creates confident misunderstanding, which is worse than admitting no diagram exists.
10
Verify the architecture through the way the system is operated
Architecture is not proved by a document. It is proved by the system's behaviour and the team's ability to change it.
Tests should protect important boundaries and rules. Static analysis can prevent one module reaching into another's internals. Contract tests can check that an integration still meets an agreed interface. Deployment pipelines can verify migrations, permissions and rollback steps. Monitoring can show whether the reliability assumptions remain true in production.
Some checks can become architectural fitness functions: repeatable tests or measurements that warn when a quality is degrading. Examples include a dependency rule that prevents the billing module importing case internals, a performance budget for a critical screen or an automated check that every background job produces a visible failure state.
Operational evidence matters too. Review incidents, support tickets, slow queries, failed jobs and difficult releases. If a part of the system repeatedly surprises the team, the architecture is giving useful feedback.
11
Evolve at the seams instead of rebuilding on principle
No team can know every important change at the beginning. Good architecture leaves options without paying for all of them in advance.
Suppose the portal's reporting workload eventually affects live case performance. Because reporting already reads through a defined boundary, the team can move heavy queries to a reporting database or data pipeline. If document processing needs different scaling, the worker can be separated without splitting the entire application. If a new customer portal needs a different release cycle, a stable API can support it.
These are evidence led changes at existing seams.
A full rearchitecture may be justified when the present structure blocks urgent business change, creates unacceptable risk or cannot meet reliability needs. Even then, replacing one boundary at a time is often safer than building a second complete system while the first one keeps changing.
Architecture should reduce irreversible bets. The aim is not to predict the final shape of the software. It is to make the next important change safer.
12
Review architecture when the business changes
Architecture is a continuing responsibility, not an approval ceremony at the start of a project.
Review it when a system gains a new class of sensitive data, a new team, a different availability requirement, a major integration or a change in commercial model. Review it after a serious incident and before a large migration. Revisit old decisions when the context recorded in the ADR is no longer true.
Keep the review grounded:
- What change is the business trying to make?
- Which quality or risk is under pressure?
- What evidence shows the current design is a constraint?
- Which decision is expensive to reverse?
- What is the simplest change that creates a safe option?
- How will the team know whether it worked?
That is architectural thinking without theatre. It connects technical structure to delivery speed, operational risk and the cost of future change.
13
Good architecture makes ordinary work less dramatic
The best architecture is often quiet. A developer can find the relevant rule. A failed integration leaves a visible record. A permission is enforced in one dependable place. A release does not require a heroic checklist. A business change reaches the right module instead of spreading across the system.
For the example portal, the valuable decisions were not a long list of technologies. They were clear business boundaries, explicit data ownership, controlled integrations, reliable operations and a record of why the trade-offs were made.
Those decisions can support a modular monolith today and a different deployment shape later. The architecture earns its keep by making that later change possible without making today's system needlessly complicated.
If an important application has become difficult to change, I can help review the structure, risks and operating model, then turn the findings into a sensible order of work.
Useful questions
Software architecture review questions
- Which business qualities must this system protect?
- Which decisions would be expensive or risky to reverse?
- Do module boundaries follow business capabilities?
- Is ownership clear for each important type of data?
- What happens when every external integration is unavailable?
- Are permissions enforced beyond the user interface?
- Can the team detect, diagnose and recover from important failures?
- Is each significant decision recorded with its context and consequences?
- Do diagrams answer a clear question at the right level of detail?
- What current evidence would justify changing the architecture?


