Software Architecture

Software Architecture Overview

Software Architecture Overview

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?”

A full list of all articles in this category, with summaries and learning points, is available at the following page.

Software Architecture — Article Indexen.senkohome.com/arch-intro-index-software/

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.

Three Major Software Architecture Patterns Choose partitioning that fits scale and organization. "Can we operate it" matters more than elegance Monolith Single Application User Products Payment 1 DB Studio Apartment Everything in one room Fastest to start building Simple operations & monitoring Small-Medium / Small Team "Monolith = outdated" is a misconception Microservices User Service Products Service Payment Service Delivery Service API Apartment Management Keys, water, contracts per unit Parallel development is a strength Dramatically higher operational cost Large-Scale / Many People & Teams Don't choose if under 30 people Modular Monolith Single App (Internal Division) User Products Payment 1 DB 3-bedroom House Rooms are separate but same house Operations as simple as monolith Easy to split later Medium-Scale / Preparing for Future Split When in doubt, this is the go-to "Splitting is always possible, merging back is hell." Starting with modular monolith is the iron rule
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).

Architecture selection sets the ceiling for AI adoption

When having AI write code, the single biggest factor affecting accuracy is the “quality of context you can hand to AI.” If type definitions and schemas exist as code, AI reads them and generates accurate code. Conversely, if the design only lives in wiki diagrams or Slack verbal agreements, AI can’t see it and you have to manually explain it every time.

The key insight: the design properties that favor AI (explicit types, standard protocols, modular separation) are exactly what has always been considered “good design.” The AI era doesn’t demand exotic architectures — teams that have been doing good design all along benefit the most from AI.

Why monoliths are structurally advantaged for AI

In microservices, specs are scattered across multiple repos. When modifying Service A, you need the API spec from Service B, the event schema from Service C, and type definitions from shared libraries all loaded into AI’s context simultaneously — just gathering information takes effort.

In a modular monolith, all type definitions, schemas, and tests live in a single repo, so AI can reference the related code at once. Boundaries are drawn logically as modules (packages) while physically managed in one repository — this configuration is the most rational default for the AI era.

Modular Monolith Architecture Image Divide a single app into modules, communicating only via interfaces Single Application (One Deployment Unit) User Controller Service Repository Entity Public API (Interface) Products Controller Service Repository Entity Public API (Interface) Payment Controller Service Repository Entity Public API (Interface) Notification Controller Service Repository Entity Public API (Interface) Direct Reference Prohibited Shared DB (One) Single repo = AI can reference all code at once Between modules, only via interface. Direct reference is prohibited Operations like monolith, structure like microservices. The go-to architecture of 2026

Mainstream tech stacks directly determine AI accuracy

Mainstream stacks like Next.js + TypeScript + Prisma have hundreds of thousands of implementation examples in public GitHub repositories. Because AI training data contains these patterns abundantly, the quality of generated code is stable.

For in-house frameworks or niche libraries, AI can’t reference similar public code, so it may get even basic usage wrong. Adding “has AI already been trained on this?” as a selection criterion is the 2026 reality.

Knowledge structure of this category

This category comprises 8 articles, divided into three groups that descend from the overall skeleton to individual design decisions.

Section Structure and Three Groups of Software Architecture From skeleton → communication → cross-cutting, descending from big picture to individual design decisions Group 1: Skeleton Define overall structure and choose tools 1. How to Choose Overall Structure Monolith / Microservices / Modular Monolith 2. How to Choose Programming Language TypeScript / Go / Rust / Java / Python 3. FW & Module Design Next.js / Spring Boot / Clean Architecture Decide structure first, then tools Group 2: Communication How to connect between modules 4. API Design REST / gRPC / GraphQL 5. Transaction Design ACID / Eventual Consistency / Saga 6. Error Handling Retry / Circuit Breaker Design communication on top of the skeleton Group 3: Cross-cutting Common themes across all communications 7. Authentication & Authorization OAuth / OIDC / JWT / RBAC 8. Session Management Cookie / JWT / Refresh Token Read alongside the Security chapter Spans all layers Designing communication without deciding the skeleton causes structure-tool mismatches

Group 1 (Skeleton) decides monolith/microservices overall structure, then selects language, framework, and module partitioning to match. Choosing language or framework before overall structure causes a mismatch between structure and tools.

Group 2 (Communication) designs how modules and services connect on top of the skeleton. REST/gRPC/GraphQL selection is covered in the API article; distributed transaction handling in the Transaction article.

Group 3 (Cross-cutting) — Auth & session management spans all communications. Read alongside the Security Architecture category’s authentication article for both implementation and policy perspectives.

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)