Software Architecture
Understand how a system's major parts are organised, how they collaborate, and how architectural decisions influence quality attributes throughout the software lifecycle.
Concept Overview
Software architecture is the set of important structural decisions that shape a software system. It describes the system's major elements, their responsibiliites, the relationships between them, and the constraints that guide their evolution. Architcture is not only a diagram: it is the reasoning behind boundaries, dependencies, data ownership, communication and deployment choices. A good architecture makes important qualities such as reliability, security, performance and maintainability achievable within the system's actual constraints.
1. Architecture describes structure and decisions
A software system can contain controllers, services, repositories, databases, queues, caches and external integrations. Architecture explais why these elements exist, what each element owns, and how requests or events move between them. The same technology can support very different architectures; selecting spring Boot or PostgreSQL does not, by itself, define the architecture. The boundaries and dependency rules around those technologies are the architectural decisions.
2. Start with requirements, not fashionable technologies
Functional requirements explain the capabilities users need. Quality attributes explain how well those capabilities must operate: availability, latency, throughput, durability, security, scalability and maintainability. Those quality goals influence the architecture. For example, a service with a modest workload and a small team may benefit from a modular application before it needs independently deployed microservices. An architecture should be justified by requirements and constraints rather than by the popularity of a technology.
- Identity users, use cases and important business workflows.
- Capture measurable qualty targets and known constraints.
- Identify data ownership, trust boundaries and failure points.
- Record important decisions and the trade-offs behind them.
3. Separate responsibilites into clear boundaries
A common application structure separates request handling, business rules and persistenc. A controller translates HTTP input into an application operation. A service coordinates business rules and transactions. A repository encapsulates data access. The purpose is not to create a class for every sentence in a requirement; it is to keep reposnsibilites cohesive and dependencies understandable. Larger applications can add moduels around business capabilites so that changes in one area do not unnecessarily affect unrelated areas.
HTTP Request
|
v
Controller
| validate and translate input
v
Service
| business rules and transaction
v
Repository
|
v
DatabaseThis is a responsibility flow, not a requirement that every application must have exactly these classe or layers.
4. Choose an architectural style deliberately
Layered architecture groups code by technical responsibility. A modular monolith deploys as one applicatio while preservig explicit internal modules. Microservices split capabilities into independently deployable services and introduce network communication, distributed data ownership and operational coordination. Event-driven architecture communicates through events and can reduce synchronous coupling, but requires careful handling of delivery, ordering, retries, and eventual consistency. Hexagonal or ports-and-adapters architecture places application rules behind interfaces so infrasructure can be replaced without rewriting the core logic.
5. Apply the ideas to the Task Management API
The supplied architecture notes begin with a modular application, PostgreSQL as the source of truth, Redis as a performance layer and message queue for asynchronous work. The application can expose REST endpoints while keeping business logic inside services. Stateless API instances can be placed behind a load balancer. This design addresses maintainability first while leaving room for horizontal scaling. Microservivces are deliberately not the starting point because their deployment and consistency costs are not justified automaticall.
6. Validate architecture continuously
Architecture should be tested against real change. Review whether modules can be changed independently, whether autorization is enforced at the server boundar, whether database transactions protect related writes, and whether logs, metrics and traces provide enough context to diagnose failures. Revisit decisions when workload, team size, security requirments or operational constraints change. Architecture is not a one-time document produced before coding; it evolves as evidence accuulates.
Key Takeaways
- ✓Architecture describes important structures, boundaries, dependencies and decisions.
- ✓Quality attributes and constraints should guide architectural choices.
- ✓A modular monolith is often a useful starting point before distributed-service complexity is justified.
- ✓Document trade-offs and revisit decisions as the system evolves.