Solution Architecture27 October 20266 min read

Architecture in Plain English — Part 2 of 8

When a module should become a microservice

Splitting a module out of an application turns a function call into a network call and a shared table into somebody else's data. Part 2 sets out five tests to apply first, and the order in which to extract when the answer is yes.

#Solution Architecture#Enterprise Architecture#Platform Engineering#Technical Debt

"We need to move to microservices" is one of the most expensive sentences in technology. It is usually said with good reason: the application is slow to change, releases are risky, and one team's work keeps blocking another's. But the sentence describes a destination, not a decision, and it skips the question that matters: which part, if any, should come out first, and what will it cost to run once it has?

This part of Architecture in Plain English uses one concrete extraction to answer that.

Marula Commerce is fictional, and its systems and figures are illustrative. Marula's shop platform holds orders, checkout, search and the product catalogue in one application with one database. The merchandising team updates the catalogue several times a day: new ranges, price changes, stock photography. Every catalogue change waits for the same fortnightly release as checkout changes, and checkout is the part nobody wants to touch casually. The catalogue looked like an obvious candidate to extract.

What actually changes when you extract

Extracting the catalogue: what actually movesBEFORE: ONE APPLICATIONOrders moduleCataloguemoduleCheckout moduleSearch moduleOne shared database(any module joins any table)AFTER: CATALOGUE SERVICEShop platform(rest of it)CatalogueserviceShop databaseCatalogue data(owned)NEW FAILURE MODEStimeouts, retries, stale copies,tracing across two processes
Before, a stock lookup is a function call and a join. After, it is a network call to a service that owns its own data, and every caller must handle that call failing.

Inside one application, the orders module asks the catalogue for a product price with a function call. It cannot time out. It does not need retries. If the catalogue table and the orders table need to be read together, a database join does it in one query, inside one transaction.

After extraction, the same question becomes a network call to another process, possibly on another machine. That call can be slow, fail, or return an answer that is a few seconds out of date. The orders team can no longer join to catalogue tables, because those tables now belong to the catalogue service and may change shape without warning.

That is the real cost of a microservice. It is not the extra container or the extra pipeline. It is that every interaction between the two parts now needs to be designed for failure, and that data which used to be shared must now be owned.

Five tests before you extract

Five tests before a module becomes a serviceTEST 1Changes on itsown rhythm?TEST 2One team canown it fully?TEST 3Owns its data,no shared joins?TEST 4Needs differentscale or uptime?TEST 5Tracing andon-call ready?any noall yesKeep it a module.Tidy the boundaryinside the application.Extract, data first.Run both paths untilthe numbers agree.
Marula Commerce passed four of five for the catalogue. The fifth, tracing across services, was built before the extraction, not after.

1. Does it change on its own rhythm? The strongest reason to separate something is that it needs to change at a different pace from its neighbours. Marula's catalogue changes daily; checkout changes monthly at most. That mismatch was the real pain.

2. Can one team own it fully? A service owned by nobody, or by three teams, is worse than a module. Ownership means building, deploying, monitoring and being woken up for it. Marula had a merchandising technology team of four that already did most catalogue work.

3. Can it own its data without shared joins? This is where most extractions fail. If other modules read the catalogue's tables directly, those reads must be replaced with API calls or with copies of the data that the catalogue publishes. Marula found eleven places in the shop platform that joined to catalogue tables. Each one had to be rewritten before the split, not after.

4. Does it need different scaling or availability? Sometimes the answer is no, and that is fine: test 1 alone can justify an extraction. But if a part has very different load (search during a sale, for example) or a different availability target, that strengthens the case.

5. Are tracing and on-call ready for a network hop? Before extraction, a slow page has one place to look. After, it has two processes and a network between them. Without distributed tracing (covered in Part 4) and a clear on-call arrangement, the first incident will be a long one.

If any answer is no, the better move is usually to tidy the boundary inside the application: give the catalogue module a clear interface, stop other modules from reaching into its tables, and see whether that already relieves the pain. A well-bounded module is also the best possible starting point for a later extraction. Our Reuse, refactor, replace or retire article covers that wider choice.

The order of extraction

When the tests pass, the sequence matters more than the technology.

  1. Draw the boundary in code first. Make every other module call the catalogue through one interface, still in the same process. This is where the eleven direct joins were removed.
  2. Separate the data. Move catalogue tables into their own schema or database while the code still runs in one application. Other modules now cannot join even if they want to.
  3. Decide how others get catalogue data. For price at checkout, Marula chose a synchronous API call with a short timeout and a cached fallback price from the last minute. For search, which needs every product, the catalogue publishes change events and the search index keeps its own copy.
  4. Stand up the service and run both paths. For a period, requests can go to the old module and the new service, and the answers are compared. Only when they agree for long enough is the old path removed.
  5. Move the route. If an API gateway sits in front (see Part 1), the public path stays the same while the backend changes underneath it.

This is slower than "build the new service and switch over". It is also the version where nobody discovers on launch day that a monthly report has been reading a catalogue column that no longer exists.

The trade-off, stated plainly

You gainYou pay
Catalogue releases without waiting for checkoutNetwork failure handling on every call
A team that owns its domain end to endDuplicated data, with a staleness window
Independent scaling of catalogue readsDistributed tracing, more pipelines, more on-call
A clearer, enforced boundaryHarder cross-domain reporting (it needs a data platform or published events)

For Marula, the gain was worth it because the release rhythm was hurting the business every week. For an application where everything changes together, the same table would argue for keeping a well-structured module, sometimes called a modular monolith, and spending the effort elsewhere.

Signs you split too early

  • Two services that must always be deployed together.
  • A "service" that cannot answer any question without calling three others.
  • A shared database that two services still both write to.
  • Incidents where nobody can tell which service caused the problem.

Each of these means the boundary is in the wrong place, or the extraction stopped halfway. The fix is rarely a better framework. It is usually moving the boundary, or merging back.

Next: Part 3, Why a successful payment can still end in a failed order. All parts are on the series page.

How CloudNala can help

We help teams decide which parts of an application are worth separating, run the five tests with the people who will own the result, and plan an extraction sequence that keeps the business running. Where the answer is "not yet", we help tighten module boundaries so that the later move is cheap.


Work with CloudNala

CloudNala helps organisations move from technology ambition to practical execution across cloud, AI, data, platform engineering and digital services.

Whether you are exploring AI, modernising your cloud environment, building a public-sector digital service, or turning an idea into a working MVP, we can help you shape the roadmap and deliver the next step.

Request an Architecture Review or write to us at consult@cloudnala.co.za