Showing posts with label microservice. Show all posts
Showing posts with label microservice. Show all posts

Cell Boundaries: Defining the Scope of a Cell in Cell-based Architecture

Mike's Notes

Pipi uses several different novel cell-like structures in its architecture, unlike the one described in this article. However, there are some good ideas here.

I went with embracing chaos and complexity. The trick is making it work.

Resources

References


Repository

  • Home > 

Last Updated

30/03/2025

Cell Boundaries: Defining the Scope of a Cell in Cell-based Architecture

By: Benjamin Cane
Medium: 2/03/2025

Builder of payments systems & open-source contributor. Writing mostly micro-posts on Medium. https://github.com/madflojo

One of the hardest questions when adopting Cell-based Architecture is defining what should and shouldn’t be within a Cell.

Defining a Cell’s boundary is crucial to ensure you’ve encapsulated everything you need while balancing its size and complexity.

Today, I will share my thought process when defining a Cell’s boundary.

Recap on Cell-based Architecture

For those who may have missed my previous posts, the TL;DR on Cell-based Architecture is that instead of building one massive system, split it into isolated groups called Cells.

Doing so will improve the system’s resilience, performance, and scalability.

To catch up, check out my recent Cell-based Architecture post.

Avoiding a Massive Cell

Ideally, every service a single request may traverse or require as a dependency should be within a Cell.

However, in a complex enterprise, a single request may trigger multiple downstream events and rely on numerous systems.

Since every component within a Cell should be tested, deployed, and failed-over together, managing such a massive system is impractical. Breaking up this customer journey across multiple Cells is better but requires thought and strategy.

Defining some Terms

Before discussing how boundaries are defined, let’s define some terms that will help ensure we are all speaking the same language.

Platform:

For this post, a Platform is a collection of sub-platforms and/or monolith systems that provide a set of functionalities for a customer journey (i.e., payment processing).

Sub-platform:

For this post, a Sub-platform is a collection of microservices that provide a clearly defined capability (e.g., account or request validations).

Region and Availability Zones:

We will also use the public cloud definitions of Regions and Availability Zones, where a Region is a separate geographical area separated by a significant distance, and availability zones are multiple isolated hosting environments close to each other but not relying on a shared resource like power, physical location, or network.

Principles

When defining boundaries, I often apply a set of principles made of rules and guidelines. While these might sound similar, the difference between a rule and a guideline is how much I’m willing to break the guidance.

I do not break the rules; they guide my decisions. A guideline is a bias, something I’m willing to ignore if it makes sense and I have good reasons (which should be written down and captured).

Rules

  • A single Cell does not span regions.

The core concept of Cell-based Architecture is to build multiple isolated systems that are carbon copies of each other rather than a single system that gains its resiliency by spreading across numerous regions.

To ensure availability, we must deploy those carbon copies in multiple Regions, with each Cell acting independently and isolated at the Region level.

A Cell might span multiple Availability Zones within a Region but it is not required.

Keeping cells within a single availability zone may be prudent if you need low latency.

Of course, this deployment approach will add operational overhead, leading to more cells, as you still need to ensure you have carbon copies in other regions. But this decision is one of those infamous trade-off moments.

  • Sub-platforms do not span multiple Cells.

Aside from the performance and failover complexities incurred by a sub-platform spanning multiple cells, keeping a sub-platform within a single cell helps solidify its responsibilities and boundaries.

The idea of a sub-platform is that external systems don’t know the internal workings of the sub-platform, only the external facing interfaces.

Is the sub-platform a microservices design, a monolith, or macroservices? It does not matter.

A sub-platform has a contract, and its owners decide its internal workings.

Extending that internal flexibility across multiple Cells becomes very complex and will likely violate other rules.

  • Components within a Cell must be tested together.

Cells might be a collection of multiple sub-platforms (more on this later), but the idea of a Cell is that it’s a single isolated unit of processing.

Whenever you deploy new capabilities or establish a new Cell, you want to ensure everything works together as expected. The best way to accomplish this is to test the entire customer journey at the Cell level.

If a customer journey spans multiple cells, testing them together may be a good idea, but ideally, the boundaries should be clear enough that cells are independently testable.

  • Failover is at a whole cell level.

In a traditional architecture where a platform is a single entity across regions, you’ll see scenarios where a single microservice fails, and traffic to that microservice is routed to another region to service new requests.

While this approach sounds excellent from an availability perspective, it’s problematic.

When a single microservice fails, the latency of a single cross-region call may not break the system, but what happens when multiple services fail? Now, a single customer request may traverse regions numerous times.

Not only is this a performance killer, but every time you traverse regions, the chances of packet loss, network failures, etc., increase — a classic “death by 1000 microservices” example.

  • Cell-to-cell communications must use fixed contracts and protocols.

Interactions between sub-platforms must follow fixed contracts and protocols, whether a REST API, a Message Queue, gRPC, or a file.

Changes within a sub-platform are okay; typically (but not always), a single team can implement them across the sub-platform.

However, we should always assume that different teams manage different sub-platforms. Changes between sub-platforms require coordination and communication across multiple teams. The same applies to Cells.

Changes between Cells always require extra coordination and testing, so we should manage them like any other API change (with versioning!).

  • Cell to Cell communications can cross Regions, but never Cell internal communications.

When defining a Cell boundary, it’s best to assume that calls between Cells may traverse regions. Cell-based Architecture acknowledges that failures will happen. A Cell will need to failover; when this happens, a request might traverse regions.

While it might be optimal to ensure Cells talk locally within a region, this is an optimization and should not be relied on for performance or resiliency.

When you assume cell-to-cell calls traverse Regions, a new set of non-functional requirements must be considered, such as retries, circuit breakers, latency, etc.

Internal Cell calls should always be local because failover is at the Cell level, not the microservice level. The whole point of Cell-based architecture is to create isolation; if internal communications traverse regions, it breaks the entire design.

Guidelines

  • Avoid Dependencies between Cells.

Some customer journeys are expansive, so encapsulating everything into a single cell can be challenging.

Building dependencies between Cells is okay, but as described above, Cell-to-Cell calls will span regions and have more non-functional concerns such as increased latency and failures.

It’s easier to manage Cells that do not depend on others, but it’s not always practical.

  • A Cell should contain a single sub-platform.

Some may argue that this guideline should be a rule, but I don’t see it as that simple.

If you can draw cell boundaries around each sub-platform, that will simplify a lot of your design. However, the practicality of a cell per sub-platform depends on your system’s use case and requirements.

If your customer journey requires low latency, having each sub-platform act as a Cell can impact your performance.

Having too many Cells also creates operational complexity, which can cause just as many issues as you are trying to prevent with Cell-based Architecture.

It’s okay to have a cell contain multiple sub-platforms; you must design it accordingly.

  • Deploy all components within a Cell together.

I firmly believe that a sub-platform’s components should be deployed together, as this reduces the complexity of releases and testing. Still, I don’t prescribe forcing Cells with multiple sub-platforms to follow this approach.

Deploying the whole Cell as one is a great practice, but it is also okay to do this at a sub-platform level.

Use discretion; this one breaks down to operational overhead, and tooling & team maturity.

  • Use Natural Boundaries to define Cell Boundaries.

A natural boundary is when a customer journey transitions from one type of architecture pattern to another, like a real-time system (REST APIs) to a batch or event-based system (Message Broker).

A real-time system takes a different approach and requires different resilience and performance from an event-based system. These changes in requirements and flow are great places to define Cell boundaries.

This guideline is not a rule, though. Sometimes, you may want to bring multiple sub-platforms and workloads into a single cell, which may mean not defining a boundary at these transition points.

By Example

Let’s explore an example system to help understand the above approach to defining Cells.

In this Example, a simple backend API calls multiple microservices (using an orchestrated microservice pattern) and triggers events to a set of event-driven microservices.

Following our principle of natural borders, the most apparent boundary is where the customer journey goes from API calls to event messages.

The event-driven systems that perform post-processing can be one Cell, while the APIs can be another.

Benefits:

  • Microservice-to-microservice calls are local within each Cell, which improves latency and reduces failure points.
  • APIs and Event-based systems can have different failover mechanisms.
  • Establishing these as two sub-platforms makes testing and releasing easier as there is a clear contract, and we can test them independently.

Why it works:

  • APIs do not have a hard dependency on event-based systems to finalize processing.
  • The event-based system has different needs and SLAs.
  • The Cells do not share the same database (a rule in microservices that applies to Cells).

Final Thoughts

While I covered many principles for defining boundaries, remember that each situation and use case is different. Guidelines are not the same as rules; they can be broken when reasonable.

However, remember the core concepts behind cell-based architecture when ignoring any guidelines.

By creating independent Cells that operate without reliance on a central dependency, you can isolate and reduce the impact and frequency of failures.

Remember these core concepts while focusing on reducing the number of times a request crosses cells, keeping cells small and manageable, and using natural boundaries.

If you do, you’ll have a resilient and performant architecture.

Pipi 7 (2020)

Mike's Notes

A Brief History of Building Pipi 7.

Resources

  • Resource

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

30/05/2025

Pipi 7 (2020)

By: Mike Peters
On a Sandy Beach: 01/03/2021

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

When Pipi 6 was finished, it was already overdue for replacement, given what I had learned from building it.

2020 Starting

The most significant change was the adoption of microservice architecture. Each microservice has a separate database, logic, workflow and web presentation layer. There were 300 microservices and lots of drawings inside 6-sided polygons.


I must have left a big trail of smoke from my Google searches, because Google started calling me every two months. Initially, I ignored them, but they wanted to host Pipi on Google Cloud Platform (GCP).

So, I optimised the internal architecture for cloud hosting on GCP using their platform tools.

A rules engine was built to handle logic. CQRS messaging that included persistent data storage.

The platform's self-documentation utilised ColdFusion.

Influences

2020 Finish

It looked good, and then it was ready for a complete rebuild (not even a refactor). However, the microservices architecture wouldn't scale because of the growing complexity caused by the Covert cell simulator-derived components. Docker wouldn't work, and it would now require a Virtual machine (VM).

Back to the drawing board.

Cliff Richardson - A Pattern Language for Microservices

Mike's Notes

Chris Richardson has a useful outline of options to choose from when considering using Microservices.
  • Good diagrams
  • Has written a book
  • Offers training
  • Has skin in the game

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library > Authors > Chris Richardson
  • Home > Handbook > 

Last Updated

11/05/2025

Cliff Richardson - A Pattern Language for Microservices

By: Mike Peters
On a Sandy Beach: 28/03/2019

Mike is the inventor and architect of Pipi and the founder of Ajabbi.

"Chris Richardson is a developer and architect with over 20 years of experience. He is a Java Champion and the author of POJOs in Action, which describes how to build enterprise Java applications with POJOs and frameworks such as Spring and Hibernate. Chris is the founder of the original CloudFoundry.com. He now spends his time providing microservices consulting and training and working on his third startup, Eventuate, Inc. Chris has a computer science degree from the University of Cambridge in England and lives in Oakland, CA."

Summary

From the home page ..."Microservices - also known as the microservice architecture - is an architectural style that structures an application as a collection of services that are

  • Highly maintainable and testable
  • Loosely coupled
  • Independently deployable
  • Organised around business capabilities.

The microservice architecture enables the continuous delivery/deployment of large, complex applications. It also enables an organization to evolve its technology stack."

Contents

Application architecture patterns

Decomposition

Deployment patterns

Cross-cutting concerns

Communication style

External API

Transactional messaging

Service discovery

Reliability

Data management

Security

Testing

Observability

UI patterns

Presentations

Chris Richardson - Documenting a service using the microservice canvas

Mike's Notes

This is a copy of an excellent blog article by Chris Richardson from his website. He also has more information about this on GitHub.
  • Use this template, which is available on GitHub.
  • Credit both Chris & Matt.
  • It closely matches what I use anyway, but it is much better laid out.
  • Most of these metadata fields are already completed.
  • The existing project documentation generator could quickly work with this template to batch output HTML and PDF files.
  • Pipi will not be using Saga's; however, it can work with workflow messaging.

Resources

References

  • Reference

Repository

  • Home > Ajabbi Research > Library >
  • Home > Handbook > 

Last Updated

11/05/2025

Documenting a service using the microservice canvas

By: Chris Richardson
Microservices.io: 27/02/2019

In What’s a service—part 1? I described the key aspects of a service, including its API and dependencies. A good way to document a service and its structure is to use a microservice canvas. A microservice canvas is a concise description of a service. It’s similar to a CRC card that’s sometimes used in object-oriented design.

I first read about the canvas in a 2017 DZone article by Matt McLarty and Irakli Nadareishvili. I’ve since adapted its structure so that it emphasises the interface (top of the canvas) and the dependencies (bottom of the canvas) and de-emphasises implementation (middle of the canvas).

Here is an example of a microservice canvas. It describes the Order Service, which is part of my book’s example FTGO application.


A service’s external view

The service’s external view is described by the following sections:

  • Name - name of the service
  • Description - a brief description of the service
  • Capabilities - the business capabilities implemented by the service
  • Service API - the operations implemented by the service and the domain events published by the service
  • Quality attributes - the service’s quality attributes, which are also known as non-functional attributes
  • Observability - includes health check endpoint, key metrics, etc.

A service’s dependencies

A service’s dependencies are described by the dependencies section, which consists of two parts.
  • Invokes - the operations which are implemented by other services that this service invokes
  • Subscribes - the messages, which include events, that this service subscribes to

A service’s implementation

The canvas can also describe the service’s implementation, such as its domain model.

Example canvas

To learn more