For thirteen weeks you have been building backends the same way: one Spring Boot application, one codebase, one PostgreSQL database. This week we zoom out and ask a bigger question: how should a whole system be organised? That is what system architecture means — how a system is split into parts, and how those parts work together.
There is no single "best" architecture, only trade-offs. This chapter introduces the three shapes you will hear about in every backend team: the monolith, the modular monolith, and microservices.
<aside> 💭
Watch the first 9:24 minutes of following video. Stop at the at end of the “Downsides of Microservices” chapter, just when mentioning Kubernetes.
</aside>
https://www.youtube.com/watch?v=rv4LlmLmVWk
A monolith is an application built as one deployable unit: one codebase, one build, one running process, and usually one database.
flowchart LR
Browser ==> App["Spring Boot application<br/>controllers + services + repositories"]
App ==> DB[(PostgreSQL)]
style App fill:#eaf8ed,stroke:#2f9e44,stroke-width:1.5px,color:#123
| Advantages | Disadvantages |
|---|---|
| One thing to build, test, run, debug and deploy | The codebase grows large and harder to navigate |
| Calling other code is just a method call — fast and reliable | You must scale the whole application, even if only one feature is busy |
| One database — simple, consistent transactions | Many teams working in one codebase step on each other |
| Easy to run locally | One serious bug can bring everything down; every deploy redeploys everything |
<aside> 💡
The monolith is the right default. Most successful products started as monoliths, and some very large ones (Shopify, Stack Overflow) still are.
</aside>
💬 Is the REST API you built in this track a monolith?
A modular monolith is still one deployable unit, but the code inside is organised into clear modules with small public interfaces between them — in Java, typically one package per business area (users, orders, billing) where other modules only call a few public classes.
<aside> 💡
Good package boundaries cost nothing today and buy you an option for later: if one module ever needs to become a separate service, the seam already exists.
</aside>
Microservices split a system into several independently deployable services. Each service owns its own database and the services communicate over the network.
flowchart LR
Browser ==> Users["users-service"]
Browser ==> Orders["orders-service"]
Orders -- HTTP --> Users
Users ==> UDB[(users db)]
Orders ==> ODB[(orders db)]
style Users fill:#e8f3ff,stroke:#2f80ed,color:#123
style Orders fill:#f3edff,stroke:#7950f2,color:#123
Teams consider microservices when: many teams need to deploy independently without waiting for each other, different parts of the system have very different scaling needs, or parts need different technology.
Why not to start with them: every arrow in the diagram is now a network call that can fail or be slow; debugging spans several machines and logs; data is spread over several databases, so keeping it consistent is genuinely hard; and you now operate, deploy and monitor N applications instead of one.
<aside> ⚠️
A distributed system is not "a monolith, but better". It trades code complexity for operational complexity. Teams that split too early pay all the costs before seeing any of the benefits.
</aside>
The progression most systems follow: monolith → modular monolith → (maybe) microservices — splitting only when there is a concrete reason.
| Monolith | Microservices | |
|---|---|---|
| Deployment | One unit | Many independent units |
| Data | One database, easy consistency | Database per service, consistency is hard |
| Failure | One process fails → everything is down | One service can fail alone, but partial failures are confusing |
| Debugging | One log, one stack trace | A request crosses several services and logs |
| Fits best | Small teams, most products | Many teams, very large scale |
<aside> 💡
"Monolith or microservices?" is a favourite junior interview question. A strong answer: "I would start with a well-structured monolith and split out services only when there is a concrete reason, like team size or scaling. Microservices trade code complexity for operational complexity." That answer sounds more senior than any list of buzzwords.
</aside>
Architecture is about how a system is split and how the parts talk. The monolith is the right default; the modular monolith keeps it tidy as it grows; microservices solve problems of scale — of teams as much as of traffic — at a real operational cost. In the next chapter you will look at how the parts of a system communicate with each other.
The following video is a classic. It shows in a humorous way how complex a microservice architecture can be in larger companies. Due to the complexity, simple features can take a very long time to be built.
https://www.youtube.com/watch?v=y8OnoxKotPQ
The HackYourFuture curriculum is licensed under CC BY-NC-SA 4.0 *https://hackyourfuture.net/*

Built with ❤️ by the HackYourFuture community · Thank you, contributors
Found a mistake or have a suggestion? Let us know in the feedback form.