Software Architecture: Consequential Structural Decisions
📑 On this page
- A concrete example: separating payments
- Architecture reflects quality requirements
- Components and responsibilities
- Data architecture
- Communication patterns
- Deployment architecture
- Architecture and organization
- Consequential versus local decisions
- Architecture decisions should be recorded
- Diagrams need purpose
- Architecture styles are starting points
- Architecture can be evolutionary
- Fitness functions
- Failure architecture
- Security and privacy architecture
- Avoid architecture astronomy
- Knowledge check
- The one idea to remember
Software architecture is often represented by boxes and arrows. The diagram is not the architecture.
Software architecture is the set of consequential structural decisions about components, responsibilities, data, communication, deployment, and system qualities.
These decisions are important because changing them later can affect many teams, interfaces, records, and operational processes.
A concrete example: separating payments
An online shop can keep payment logic inside one application or place it behind a separate service.
A separate payment service may provide:
- Independent security boundary
- Dedicated ownership
- Separate scaling
- Controlled access to payment credentials
It also introduces:
- Network failure
- API versioning
- Distributed transactions
- More deployment and monitoring
- Operational ownership
Architecture is the reasoning behind this boundary and its consequences, not the rectangle labeled Payment Service.
Architecture reflects quality requirements
Architecture is shaped by desired qualities:
- Availability
- Performance
- Security
- Modifiability
- Scalability
- Auditability
- Cost
If a system must survive a data-center failure, it needs deployment and data strategies across failure domains.
If a report may take twelve hours, a simple batch architecture may be appropriate.
There is no universally best architecture. There is an architecture that better fits a particular set of forces.
Components and responsibilities
A component is a meaningful unit with a responsibility and interface.
Examples:
- Web application
- Payment module
- Database
- Queue consumer
- Identity provider
- Mobile client
Good boundaries answer:
- What does this component own?
- Which data can it change?
- Which interface does it expose?
- Who operates it?
- How does it fail?
If several components believe they own the same rule or table, changes become risky and coordination grows.
Data architecture
Architecture includes:
- Data model
- Source of truth
- Storage technology
- Ownership
- Replication
- Retention
- Backup and recovery
- Privacy controls
Splitting application code while keeping one shared database can preserve tight coupling.
Giving every service its own database creates clearer ownership but makes cross-service queries and transactions harder.
Data boundaries usually outlive code refactors and deserve careful design.
Communication patterns
Components communicate synchronously or asynchronously.
Synchronous request:
Checkout -> Payment API -> immediate responseAsynchronous event:
Order created -> queue -> email workerSynchronous communication is direct but couples availability and latency.
Asynchronous communication absorbs bursts and decouples timing, but adds queues, eventual consistency, duplicate delivery, and harder tracing.
Choose based on whether the caller needs an immediate result and how failures should behave.
Deployment architecture
Logical components must run somewhere.
Deployment decisions include:
- Process boundaries
- Containers or VMs
- Regions and zones
- Network paths
- Scaling units
- Storage attachment
- Secrets and identity
Two modules in one process communicate differently from two services across a network.
A network boundary adds serialization, authentication, latency, partial failure, and version compatibility.
Deployment is not an afterthought. It changes the programming model.
Architecture and organization
Software boundaries often reflect communication boundaries among teams.
If three teams independently change one tightly coupled application, coordination becomes a bottleneck.
If one small team owns ten microservices, operational overhead may overwhelm it.
Architecture should fit:
- Team size
- Ownership
- Skills
- On-call model
- Release process
- Communication needs
Changing architecture without changing organizational responsibility often produces confusing ownership rather than autonomy.
Consequential versus local decisions
Not every decision is architectural.
Choosing a local variable name is usually easy to change.
Choosing:
- The authoritative customer identifier
- A public API contract
- A consistency model
- A cloud region
- A service boundary
- An encryption-key strategy
can be expensive to reverse.
Architecture focuses attention on decisions with broad impact, long life, or difficult migration.
Architecture decisions should be recorded
An architecture decision record can capture:
- Context
- Decision
- Alternatives considered
- Consequences
- Status
- Date and owner
Example:
Decision: Use asynchronous events for customer email.
Reason: Checkout must not depend on email-provider latency.
Consequence: Email can be delayed or duplicated, so consumers require
idempotency and queue monitoring.The record preserves why a choice made sense.
Without context, future teams may repeat old debates or remove an important constraint accidentally.
Diagrams need purpose
Different diagrams answer different questions:
- Context diagram: users and external systems
- Container diagram: major applications and data stores
- Component diagram: internal responsibilities
- Deployment diagram: runtime placement and networks
- Sequence diagram: one interaction over time
- Data-flow diagram: where information travels
One diagram cannot show everything clearly.
Label trust boundaries, protocols, ownership, and sources of truth where relevant.
A diagram that cannot answer a reader's question is decoration.
Architecture styles are starting points
Common styles include:
- Layered architecture
- Modular monolith
- Microservices
- Event-driven architecture
- Pipes and filters
- Hexagonal architecture
- Client-server
Styles provide vocabulary and known tradeoffs.
They are not complete designs.
Two systems both called microservices can differ radically in data ownership, deployment independence, service size, and operational maturity.
Use patterns to support reasoning, not replace it.
Architecture can be evolutionary
Not every future decision must be made now.
An evolutionary architecture:
- Uses replaceable boundaries
- Avoids unnecessary irreversible choices
- Measures important qualities
- Supports incremental migration
- Records assumptions
A modular monolith can preserve domain boundaries and later extract a service when independent scaling or ownership becomes real.
Evolution is not unplanned change. It is deliberate ability to adapt while protecting important properties.
Fitness functions
An architectural fitness function is an automated or repeatable check for a desired property.
Examples:
- No module outside billing imports billing internals.
- Every public API remains backward compatible.
- No production storage is publicly accessible.
- The checkout path stays under a latency target.
- Services may depend only in an allowed direction.
Fitness functions turn architecture from a document into continuously checked evidence.
Not every quality is fully automatable, but recurring checks prevent silent erosion.
Failure architecture
Ask:
- What if this component is unavailable?
- What if the request times out after succeeding?
- What if an event arrives twice?
- What if one region loses network access?
- What if data restoration returns an earlier point?
Architecture determines whether failures remain local or spread.
Bulkheads, timeouts, idempotency, queues, circuit breakers, and graceful degradation are structural tools.
Reliable architecture describes recovery paths as carefully as happy paths.
Security and privacy architecture
Architecture sets:
- Trust boundaries
- Identity flow
- Permission scope
- Data movement
- Encryption layers
- Audit points
- Retention and deletion
Security cannot be added only at the user interface.
If every service shares one administrator credential or sensitive data is copied everywhere, later controls face a bad structural foundation.
Threat modeling should influence component and data boundaries early.
Avoid architecture astronomy
Architecture can become detached from implementation through:
- Speculative diagrams
- Unowned standards
- Technology chosen for prestige
- Boundaries no team can operate
- Documents that never reflect production
Architects and developers need feedback from code, incidents, users, costs, and operations.
The architecture is what the system actually does under change and failure, not what the slide deck claims.
Knowledge check
- Why is a diagram not itself software architecture?
- How do quality requirements shape architecture?
- What costs appear when communication crosses a network boundary?
- What should an architecture decision record preserve?
- How does a fitness function keep an architectural intention alive?
The one idea to remember
Software architecture is the set of structural decisions whose consequences spread widely and are costly to reverse. Make those decisions from explicit quality needs, record their tradeoffs, and verify that the running system still honors them.