SkillGridLearn computer science by doing

One program or many: monoliths and services

Splitting a system into services is a trade, not an upgrade. This lesson is about what each shape buys and what it costs.

15 min · 48 XP

You now have a server, an API contract, and caches in front of it. All of that still fits inside one program: one process, started once, answering every request. That is a monolith, and it is how almost every system starts. The interesting question is not whether a monolith is old-fashioned. It is what happens to this single program when the company grows, and whether breaking it into pieces really helps.

A monolith is one deployable unit. The code that renders the page, the code that charges the card, and the code that sends the email all live in the same program, share the same memory, and are released together. When one part calls another, it is an ordinary function call: microseconds, and either it returns or it throws. There is one database, so joining data across features is a query, not a network round trip. There is one log file to read.

UserOne programOne databasesearch for a bookread the cataloguerowsresultsone process, one deploy, one log file
                     MONOLITH                  SERVICES
                   ----------------------    ----------------------
processes to run   one                       many
deploys            one for everything        one per service
where you debug    one stack trace           a trace across five logs
scaling            copy the whole thing      copy only the busy part
data               one database, easy joins  split, joins become calls
failure            one crash hurts all       one crash stays containedEvery gain on the left becomes a cost on the right; neither column is free.

What a monolith gives you is enormous and easy to undervalue. Deploying is one action, so a change to the payment code and a change to the page text ship together and are tested together. Debugging is one stack trace: when a request fails, you follow it through the same program, in one log, with no question about which version of which service was running. A transaction can be real: charging the card and marking the order paid either both happen or neither does. And refactoring is cheap — moving a function between two files is a code change, not a project.

Here is where the costs actually land. Scaling: you no longer copy one program, you decide which parts to copy and how they find each other. Failure: a function call returns or throws, but a network call has a third outcome — it hangs, or it succeeds and the answer is lost on the way back. Suddenly you need timeouts, retries, and the discipline that retrying a payment must not charge twice. Debugging: one user action now crosses five services, and the stack trace you relied on is replaced by a search across five logs, which only works if somebody made every service write a shared request id. Consistency: the database is split, so the transaction that used to be free now has to be built by hand, and it is called a saga.

The deepest of these costs is the one beginners never see coming: the network is not free, and it is not reliable. Inside one program, calling a function is so cheap and so certain that you stop thinking about it. Between two services, every call can take a hundred times longer, can fail on its own, and can be slow in a way that eats a thread and takes down the caller. Code that was a simple loop over five items becomes five sequential round trips. Architecture at this level is mostly the study of which calls you can afford to make across a boundary.

Practice

  1. Checkout calls the inventory service to reserve an item. What can go wrong here that could not go wrong inside one program?

    Hints
    • A function call inside one program either returns or throws; it cannot be half-answered.
    • A remote call travels over the network, and the network has a third outcome.

    15 XP

  2. Match each problem with the shape that makes it worse.

    Hints
    • Debugging pain comes from the number of places you must look, not from the amount of code.
    • Scaling pain comes from being forced to copy parts that are not busy.

    15 XP

  3. Put the honest path from one program to several services in order.

    Hints
    • You cannot draw a border around something you have not located yet.
    • The last step is the expensive one, so it comes only after the cheap ones prove it is worth it.

    18 XP