Polylith in a Nutshell

Polylith is a software architecture that simplifies our backend services and tools by enabling us to construct them as “modular monoliths” using composable building blocks.

Here we explain the basic concepts of Polylith.

Function

Functions are the smallest building blocks in Polylith from which everything is created. Most communication within a Polylith system is done by using simple function calls as a way to connect the different high-level building blocks that a Polylith system consists of.

The simplicity of functions makes them fantastic building blocks for code:

  1. Encapsulation: functions hide their implementation and only expose their signature.

  2. Simplicity: functions have a single responsibility and don't mix nouns with verbs, which makes them fundamentally untangled.

  3. Stateless: functions are just code; they don't contain state or instance.

  4. Purity: functions can be pure (i.e. have no side-effects) which makes them easy to understand, reuse, test and parallelise.

These properties make functions (especially pure functions) inherently composable and testable units of code and a perfect foundation for a software architecture like Polylith.

Library

A library is the kind of library we already know, a chunk of code that is compressed into a versioned file which can be downloaded from Maven, Clojars or other repositories.

A library is a piece of code that lives in its own namespace which allows us to pick the libraries we want to use, without getting into name clashes (but sometimes dependency hell!).

We rely on tooling we already use, that hides the complexity of solving dependencies to other libraries and the caching of files on disk.

Component

Components are high-level building blocks (bricks) which remove the need for layers (horizontal, vertical slice, or onion) in our architecture.

A component can represent a part of our domain (e.g. cart, invoice, order, user, etc.), or be part of our infrastructure (e.g. authentication, database, log, etc.), or be an integration point to a third-party system, (e.g. crm-api, payment-api, sms-api, etc).

Base

A base is a special type of building block (brick) that only exposes its functionality via a public API, e.g. REST, Lambda, GraphQL, gRPC, command-line, etc.

A base exposes a collection of endpoints via its API, and delegates the implementation of each endpoint to an appropriate component.

Brick

Brick is the common name for a component or base, which are our building blocks (together with libraries).

Project

A project specifies which libraries and bricks should be included in an artifact, like a service, lambda function or command line tool. This allows for optimal code reuse of components across multiple projects.

Development project

A development project is the place we use to work with all our libraries, components, and bases. It gives us a “monolithic development experience” with full code navigation, debugging, and refactoring across our entire codebase, and the possibility to work with our entire system in a single REPL.

Workspace

A workspace is the place in a Polylith codebase where we store all our building blocks and configure our projects.

Now, let's dig deeper into the Polylith architecture to better understand how it solves these challenges.

Last updated