About this article
This article is the entry point of the “Software Architecture” category in the Architecture Crash Course for the Generative-AI Era series, surveying the domain at the bird’s-eye level.
Layered, DDD, hexagonal, clean, microservices, modular monolith — this is the most ideologically fragmented field in the entire stack. This article surveys the major structural patterns and gives you the practical decision axis: “can our scale, skill, and timeline actually run this?”
What is software architecture in the first place
Imagine a building’s structural design. Timber, steel, or reinforced concrete — the choice of skeleton determines the scale you can build, the ease of renovation, and the structure’s lifespan. Interior design (application architecture) sits on top of this skeleton, so changing the skeleton later is an enormously expensive undertaking.
Software architecture is the domain that decides an application’s overall structure — monolith, modular monolith, microservices, etc. It encompasses skeletal decisions such as language selection, API design, and DB connection strategy.
If you start development without deciding the software architecture, as the codebase grows the code tangles together, and every change breaks something unexpected.
Why software architecture matters
Structural choices can’t be undone later
Migrating from monolith to microservices costs closer to “rebuilding” than “remodeling.” The structure you pick at the start determines the team’s development velocity, scalability, and operational burden.
Scale-architecture mismatch is fatal
A 3-person team running microservices gets crushed by operations; a 100-person team maintaining a monolith jams the deploy pipeline. Choosing the structure that matches your organization’s scale is the architect’s most important call.
Design-philosophy choices set the code’s lifespan
Layered, DDD, Clean Architecture — philosophies abound, but the practical answer is to choose by the single criterion of “can our team run it?”
A domain full of holy wars
This area pairs with system architecture by focusing on “the external structure of the application — the heart of the system being constructed.” Decisions made here also propagate strongly into application architecture, so consistency between the two matters.
Every school of thought has both supporters and detractors, and social media hosts a daily holy war. But what matters in practice is not “which doctrine is truly correct” but the single question “can our team actually run it?”
Beautiful design that nobody can run is meaningless; ugly design that the team can run is a success. The decision axis is not doctrine — it is whether your scale, skills, and timeline can keep it alive.
The three big patterns of overall structure
Software architecture’s overall structure splits into three large patterns.
flowchart LR
M["Monolith<br/>(All features in one app)"]
MM["Modular monolith<br/>(One app, internally split)"]
MS["Microservices<br/>(Independent service per capability)"]
M -- "Scale up,<br/>org grows" --> MM
MM -- "30+ people /<br/>independent deploys" --> MS
MS -. "Post-mortem on over-decomposition" .-> MM
classDef mono fill:#dbeafe,stroke:#2563eb;
classDef mod fill:#fef3c7,stroke:#d97706;
classDef micro fill:#fae8ff,stroke:#a21caf;
class M mono;
class MM mod;
class MS micro;
| Pattern | Trait | Fits |
|---|---|---|
| Monolith | Traditional structure: everything in one app | Small-to-mid scale / small teams |
| Microservices | Each capability as an independent service | Large scale / many people, many teams |
| Modular monolith | Monolith with explicit internal modular boundaries | Mid scale / preparing for future split |
In housing terms: monolith = a studio (everything in one room), modular monolith = a 3-bedroom house (rooms separated, same house), microservices = renting out each unit of an apartment building (free per unit, but keys/water/contracts handled individually). That framing maps scale to load.
Reaching for “apartment-building management” before the studio gets cramped guarantees you’ll exhaust yourself collecting rent.
Monolith vs Microservices
| Aspect | Monolith | Microservices |
|---|---|---|
| Ease of starting | Excellent — simple | Poor — complex |
| Small-scale ops | Excellent — easy | Bad — overkill |
| Large-scale, multi-team | Poor — frequent merge conflicts | Excellent — parallel work |
| Deploy unit | Whole app at once | Per-service |
| Blast radius | Propagates everywhere | Easier to isolate |
“Microservices from day one” is the canonical over-engineering case. Modular monolith is the current default; gradual splitting begins after the org crosses ~30 people.
“Splitting is always an option later, but unsplitting is hell.” Start with modular monolith.
What you must decide — what’s your project’s answer?
For each of the following, articulate your project’s answer in 1-2 sentences. Leaving them ambiguous now will always come back as “why did we decide that?” later.
Structure / language / framework
| Item | Examples |
|---|---|
| Overall structure | Monolith / Microservices / Modular monolith |
| Module design | Layered / Domain-Driven / Hexagonal |
| Programming language | Java / C# / Python / Go / Rust / TypeScript … |
| Framework | Spring / .NET / Next.js / Django … |
| App server | Spring Boot / Tomcat / Gunicorn / Node.js … |
Communication / auth / transactions
| Item | Examples |
|---|---|
| API style | REST / GraphQL / gRPC / WebSocket |
| Transaction design | ACID (the four DB consistency guarantees) / Eventual consistency / Saga (compensation-based pattern for distributed transactions) |
| Error handling | Exception policy / Retry / Circuit Breaker (cuts off calls after consecutive failures) |
| Logging | Structured logs / Correlation IDs / Aggregation backend |
| Encryption | In-transit / at-rest policy |
| Session management | Cookie / JWT (JSON Web Token, signed token) / Refresh Token |
Scale × structure ladder
In software architecture, the recommended structure is mostly determined by team headcount. Conway’s Law (the empirical observation that org structure determines system structure) is heavily in play.
The conclusion up front: 1-10 people → TypeScript single-DB monolith is plenty. Promote to modular monolith at 10-30. Carve out partial microservices once you exceed 30. As of 2026, this is the route with the lowest failure rate.
| Team size | Recommended structure | DB | Languages | API style |
|---|---|---|---|---|
| 1-3 | Monolith | 1 DB | 1 (TS, etc.) | REST |
| 3-10 | Monolith → Modular monolith | 1 DB | 1-2 | REST + some WebSocket |
| 10-30 | Modular monolith | 1-2 DBs | <=2 | REST + internal gRPC |
| 30-100 | Modular + partial microservices | Per use case | 2-3 | REST + gRPC + events |
| 100+ | Microservices (core) + modular monolith (operational domains) | Per service | 3-5 | gRPC + Kafka |
The practical floor for microservices is “30+ team members + 5+ dedicated ops engineers.” Cases like Segment’s 140-service reversal to monolith (2020), or Amazon Prime Video’s 2023 consolidation from serverless+microservices into a monolith with 90% infrastructure cost reduction, are textbook: distribution out of scale always breaks down.
Start with modular monolith. Splitting is always an option later. Unsplitting is hell.
Architecture-level traps
The forbidden moves at the software-architecture level:
| Forbidden move | Why |
|---|---|
| Microservices below 30 people | Same ending as Segment 2020, distributed-TX swamp |
| Adopting new tech without information density or talent | Nobody can write it 5 years later, project goes stale |
| Schemaless DB for strong-consistency workloads | The classic MongoDB story; start with PostgreSQL |
| Build auth in-house | Holes everywhere; delegate to Auth0 / Clerk / Firebase Auth |
| Publish APIs without a schema | Make it explicit with OpenAPI / Protobuf / GraphQL Schema |
| Run 2PC (Two-Phase Commit) in cloud production | Network partition halts everything; switch to Saga + Outbox |
| 5+ languages mixed in one project | Maintainers get scattered; <=2 is healthy |
| Monolith without module boundaries | Once past 10 people, change conflicts pile up; draw boundaries from day one |
| Choosing microservices for performance | Inter-service communication overhead can make things slower; vertical scaling comes first |
| Mimicking DDD pattern names without organizing business vocabulary | Just adds classes — over-engineering with zero payoff |
Software architecture is a function of scale and maturity. Pick by the pain you actually feel.
AI decision axes
| AI-era favorable | AI-era unfavorable |
|---|---|
| Designs explicit in code (types, schemas, constraints) | Tribal knowledge, ad-hoc operational rules |
| Mainstream combinations (Next.js, Spring Boot, etc.) | Niche or in-house frameworks |
| Modular monolith + standard protocols | Complex microservices + proprietary protocols |
| Single repo where the whole thing is visible | Specs scattered across many repos |
- Look at scale and team structure first; avoid over-engineering (default to monolith-family).
- Pick mainstream language and framework (it determines AI-era productivity).
- Lean on standard protocols (REST / gRPC / OIDC …).
- Make types, schemas, and constraints explicit in code (designs AI can read).
Selection by case
New web service (startup, early SaaS)
Modular monolith + TypeScript + Next.js + REST + cookie sessions. Reconciles speed of starting and ease of splitting later — the current default. Single-DB ACID, no distributed transactions: the configuration least likely to invite bugs.
Splitting up an existing monolith
Phase-migrate to modular monolith → carve out only the genuinely bottlenecked features. Full microservices migration just spikes ops cost without commensurate business value. Saga + Outbox (write the message together with the DB update so it can be reliably delivered later) only enters the picture once you actually carve something out.
Mission-critical systems with complex business logic (finance, insurance, healthcare)
Spring Boot or ASP.NET Core + Clean or Hexagonal + DDD + strong consistency (ACID). Long-lived domains heavy with business rules pay back the investment in protecting the domain from external dependencies. OIDC + SSO foundation for unified permission management is the standard.
SaaS / consumer services expecting traffic spikes
Modular monolith + eventual consistency on the read path + CDN + cache layer. Keep writes strongly consistent, scale reads horizontally with eventual consistency. Healthier than premature microservices: identify the bottleneck and scale that part.
Summary
This article served as the entry point for the “Software Architecture” category, surveying the domain.
This is an ideologically fragmented field, but the decision axis boils down to “can our team run it?” The 2026 default: modular monolith + mainstream framework + standard protocols, anchored on the principle “AI-friendly = human-friendly.”
The next article opens the deep dive: how to choose a programming language.
Back to series TOC -> ‘Architecture Crash Course for the Generative-AI Era’: How to Read This Book
I hope you’ll read the next article as well.
📚 Series: Architecture Crash Course for the Generative-AI Era (17/89)