Two Boundaries

Chapter 3, “Deploying a Monolith,” ended with the deployment boundary as a design decision. A boundary is the line around one deployable unit. Everything inside the line is released together, fails together, is scaled together, and is owned by one team. That chapter drew one boundary around one application and gave four consequences the designer has to accept: failure, change, capacity, and ownership.

This chapter has two applications, the registrar’s system and CourseTracker, and each one has its own boundary. The API is the one place where the two boundaries touch. Nothing gets from one side to the other except through it. CourseTracker cannot see the registrar’s tables, its code, or its server. It sees requests and responses. So from the outside, the API is where the registrar’s system ends. The four consequences from chapter 3 now come from having two boundaries instead of one, and the API is where each of them is handled. We have already made the decisions that handle each one.

Failure

Two systems with an API between them fail separately. When the registrar’s system is down, the API sends 500 or 503, and CourseTracker’s search stops working. The rest of CourseTracker keeps working. A student can still open their course history, because that reads CourseTracker’s own tables. That is a consequence of the decision, made in chapter 7, that CourseTracker keeps its own copy of what its users have added. The boundary also means CourseTracker has to be written for the case where the API does not respond. If CourseTracker assumes every request succeeds, it crashes when the registrar’s system is down.

Change

Each side changes without telling the other first. The registrar’s office can rewrite its system, change its database, and move to a new hosting platform, and CourseTracker does not know. CourseTracker can do the same. Each side only has to keep the API fixed, and the versioning section is what lets even the API change. A breaking change goes into a new version, the old version keeps running until its retirement date, and the client moves when it is ready. Compare this with the direct database connection from chapter 7, where a renamed column in the registrar’s database broke CourseTracker as soon as the column was renamed.

Capacity

The registrar’s system has a fixed capacity. It can handle only so many requests per second before it slows down, and the registrar’s own staff share that capacity with every client of the API. The API decides how much of that capacity clients may use. Caching keeps most requests from reaching the registrar’s system at all. Rate limits cap what any one client can send. Load shedding refuses requests when the total is still more than the registrar’s system can take. These three decisions meet the isolation requirement, and they are made at the boundary.

Ownership

The boundary also decides who is responsible for what. The registrar’s office owns the catalog and everything on its side of the API. CourseTracker’s developers own the history and everything on their side. Neither team needs to read the other’s code. What they share is the documentation, which says what each request looks like and what each response looks like. That page is the agreement between the two teams.

Making the API public changes who the registrar’s office has an agreement with. Instead of one team it can call, it has an agreement with every developer who has read the documentation. The registrar’s office does not know who those developers are, so it cannot warn them one by one before a change. This is why the retirement date of a version is published in the documentation.