Software Architecture

Software Architecture Overview — Navigating a Domain Full of Camps

Software Architecture Overview — Navigating a Domain Full of Camps

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;
PatternTraitFits
MonolithTraditional structure: everything in one appSmall-to-mid scale / small teams
MicroservicesEach capability as an independent serviceLarge scale / many people, many teams
Modular monolithMonolith with explicit internal modular boundariesMid 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

AspectMonolithMicroservices
Ease of startingExcellent — simplePoor — complex
Small-scale opsExcellent — easyBad — overkill
Large-scale, multi-teamPoor — frequent merge conflictsExcellent — parallel work
Deploy unitWhole app at oncePer-service
Blast radiusPropagates everywhereEasier 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

ItemExamples
Overall structureMonolith / Microservices / Modular monolith
Module designLayered / Domain-Driven / Hexagonal
Programming languageJava / C# / Python / Go / Rust / TypeScript …
FrameworkSpring / .NET / Next.js / Django …
App serverSpring Boot / Tomcat / Gunicorn / Node.js …

Communication / auth / transactions

ItemExamples
API styleREST / GraphQL / gRPC / WebSocket
Transaction designACID (the four DB consistency guarantees) / Eventual consistency / Saga (compensation-based pattern for distributed transactions)
Error handlingException policy / Retry / Circuit Breaker (cuts off calls after consecutive failures)
LoggingStructured logs / Correlation IDs / Aggregation backend
EncryptionIn-transit / at-rest policy
Session managementCookie / 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 sizeRecommended structureDBLanguagesAPI style
1-3Monolith1 DB1 (TS, etc.)REST
3-10Monolith → Modular monolith1 DB1-2REST + some WebSocket
10-30Modular monolith1-2 DBs<=2REST + internal gRPC
30-100Modular + partial microservicesPer use case2-3REST + gRPC + events
100+Microservices (core) + modular monolith (operational domains)Per service3-5gRPC + 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 moveWhy
Microservices below 30 peopleSame ending as Segment 2020, distributed-TX swamp
Adopting new tech without information density or talentNobody can write it 5 years later, project goes stale
Schemaless DB for strong-consistency workloadsThe classic MongoDB story; start with PostgreSQL
Build auth in-houseHoles everywhere; delegate to Auth0 / Clerk / Firebase Auth
Publish APIs without a schemaMake it explicit with OpenAPI / Protobuf / GraphQL Schema
Run 2PC (Two-Phase Commit) in cloud productionNetwork partition halts everything; switch to Saga + Outbox
5+ languages mixed in one projectMaintainers get scattered; <=2 is healthy
Monolith without module boundariesOnce past 10 people, change conflicts pile up; draw boundaries from day one
Choosing microservices for performanceInter-service communication overhead can make things slower; vertical scaling comes first
Mimicking DDD pattern names without organizing business vocabularyJust 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 favorableAI-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 protocolsComplex microservices + proprietary protocols
Single repo where the whole thing is visibleSpecs scattered across many repos
  1. Look at scale and team structure first; avoid over-engineering (default to monolith-family).
  2. Pick mainstream language and framework (it determines AI-era productivity).
  3. Lean on standard protocols (REST / gRPC / OIDC …).
  4. 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.