Systems are one or more services collaborating to offer a unified set of functionality to the outside world.

Sometimes a single service isn't enough to meet our performance or operational needs. That's when we have to scale our solution horizontally, by getting multiple services working together in an system.

Two Polylith services ready to be connected into a system

There are two reasons to add a new service into an system:

  1. when you've hit a performance/scalability bottleneck

  2. to gain operational benefits (for example, to separate your batch processing from your main service)

In Polyith, we don't need to create new services to structure our domain into managable and encapsulated modules. That's what components are for.

Service-B connected to an endpoint offered by Service-A's API

The simplest multi-service system we can visualise involves two services. We can imagine them being connected via a "cable" which extends from an external dependency in a component in Service-B to an endpoint in Service-A's base.

One of the advantages with Polylith is how easy it is to share components across multiple services within a workspace. It's a component's functional and stateless nature that makes it perfect for reuse. For example, if both Service-A and Service-B need to access the same database, then they can use the same database component.

It can be a useful pattern to make just one service act as the API for an entire system. This makes use of the same encapsulation concept as the interface and implementation layers in a component and base. It allows us to offer a single place to access the system's functionality, whilst hiding unnecessary implementation details.

But what is it like to work with Polylith?

Hopefully the building block metaphor has given you a high-level understanding of the Polylith architecture.

Now let's take a closer look at how Polylith structures your code, and gives you a workspace to play with these building blocks.