Cell Based Architecture
Safe evolution under scale - from monoliths to microservices to shards to cells
▸$cat summary.txt
This post covers Cell Based Architecture. Safe evolution under scale - from monoliths to microservices to shards to cells
Prologue
The question that started this essay is deceptively simple: how do you build a SaaS product that can evolve safely at scale? Not scale throughput. Not scale teams. But scale change - without every deployment feeling like a bet-the-company event.
Throughout my tenure at Atlassian, I watched how deeply infrastructure abstraction shapes organizational velocity. The difference between a startup shipping freely and an enterprise moving cautiously isn't just process, it's architecture. The isolation boundaries you choose determine how fast you can safely evolve.
This essay is the distillation of that observation. It traces the natural evolution of isolation boundaries - from monoliths to microservices to shards to cells - and explains why the industry is converging on cell-based architecture as the primitive for fleet-level safety.
A long-form systems engineering essay on how isolation boundaries evolve under operational pressure. Not a tutorial. Not a sales pitch. A causal chain from first principles to production reality.
Traditional Service Architecture
It is remarkably easy to build a service that works for a hundred customers. Spin up an EC2 instance, connect it to RDS, put a load balancer in front, and you have a standard three-tier application with reasonable separation of concerns.
Scale that to a thousand customers, and you add Auto Scaling Groups. Ten thousand, and you introduce caching layers, read replicas, and queue-based load shedding. The architecture grows technically - more instances, more redundancy, more throughput.
But underneath all of that growth, something critical remains unchanged: everything is shared. Every customer's requests hit the same load balancers, the same database cluster, the same deployment pipeline. The system scales technically, but operationally everything stays coupled.
This coupling is invisible during normal operation. It only reveals itself during failure. A bad deployment doesn't just affect the team that shipped it - it affects every tenant on the platform. A misconfigured migration doesn't just slow down one query pattern - it risks the entire datastore.
The default architecture is not wrong. It is correct for its domain. But the domain changes when the cost of shared fate exceeds the cost of partitioning.
When the cost of shared fate exceeds the cost of partitioning, the natural evolution is to partition the service itself. What follows is service sharding - the first isolation boundary.
Service Sharding
The first architectural insight is that not every customer needs to share the same runtime.
A load-balanced fleet of identical service instances is replication, not sharding. This distinction matters enormously.
| Dimension | Service Replication | Service Sharding |
|---|---|---|
| State | Stateless | Stateful |
| Request Routing | Any instance can serve any request | Each request has a correct shard |
| Load Distribution | Random / Round Robin / Least Loaded | Deterministic based on routing key |
| Failure of One Instance | Other instances pick up traffic | Only customers on that shard are affected |
Service sharding partitions a service into multiple operationally-independent instances called shards. Each shard owns everything needed to serve its slice of customers - its own compute, its own database, its own deployment lifecycle.
The advantages follow from the isolation:
- Independent - Shards share no state, deployments, or failure domains.
- Complete - No shard depends on another to serve its requests.
- Subset - Each customer belongs to exactly one shard, determined by a routing key.
What Makes a Shard?
A shard is not just a database partition. For it to serve as a complete operational unit, it needs:
- A unique shard name and environment assignment (dev, staging, prod, prod-eu)
- The service or services it hosts
- Region, availability zone, and topology metadata
- A type - for tainting or capability tagging
- Service mesh or sidecar integration for cross-shard communication
Routing to a Shard
Once sharded, every request must reach its correct shard. This requires a resource identifier that encodes the routing decision.
Atlassian uses ARI (Atlassian Resource Identifier) which encodes the cloud ID, service, and resource type - enabling deterministic routing without external lookups for every request.
ari:cloud:beacon:<cloud-id>:workspace/<workspace-id>
ari:cloud:beacon:<cloud-id>:alerts/<alert-id>
This pattern allows the infrastructure to determine the target shard purely from the request path, without querying a routing table on every call.
A separate shard registry service tracks all active shards and their assignments. A companion sharding service handles allocation and de-allocation of shards as tenants are onboarded or migrated.
The Cost of Sharding
Sharding is not free. It introduces several hard problems:
Cross-shard operations are expensive. Querying across shards means crossing operational boundaries - authentication, authorization, network hops. Aggregation, search, and analytics all become significantly harder.
Shard migrations are extremely difficult. Moving a tenant from one shard to another means migrating their data, draining in-flight requests, draining queue messages, and maintaining consistency - all without downtime. This is a substantial engineering challenge on its own.
Capacity rebalancing is necessary. A noisy tenant can saturate a shard while others remain idle. The options are shard splitting, tenant migration, or finer-grained sharding - none of them trivial.
Cognitive cost for teams. Developers must pick a sharding key, register it in the shard registry, refactor cross-tenant logic, and maintain per-shard observability. The operational surface area grows.
But sharding isolates a single service. Real incidents cascade across services. What follows is the realization that we need isolation at the fleet level - not just the service level.
Why Sharding Is Not Enough
Sharding isolates one service. But companies are not one service - they are fleets of services.
| Guarantee | Sharding | What we actually want |
|---|---|---|
| Blast Radius | When service X fails, only 10% of X's customers are affected | When *anything* fails, only 10% of *all* customers are affected |
| Cross-Service Coordination | Sharding is per-service | Cells span multiple services |
| Deployment Safety | One service deploys independently | A coordinated fleet deploys safely |
This is the critical gap. Sharding gives you isolation within a service boundary. But a real production incident rarely stays within one service. A bad deployment to the auth service, a misconfigured message broker, a runaway query against the shared analytics pipeline - these cascade across service boundaries because the infrastructure itself is shared. The problem is not service-level coupling. The problem is fleet-level coupling.
And this brings us to the real question: how do you isolate failure domains at the fleet level, not just the service level?
Fleet-level coupling creates organizational friction that compounds with every new team and every new feature. This friction manifests as the problems of 100× scale.
When a system grows 100×, the failure modes evolve from technical problems to organizational problems. The challenge is no longer handling traffic, it is managing change safely in a deeply shared environment.
A single faulty commit can bring down every tenant. An infrastructure migration that touches shared state becomes a bet-the-company event. Rollback strategies that worked at small scale become operationally paralyzing at large scale.
"Scaling infrastructure becomes easier than scaling trust."
The problems compound:
Noisy neighbor problems mean one aggressive tenant can degrade the entire platform.
Deployment paralysis means teams stop shipping because the risk of breaking something shared is too high.
Architectural drift means the system becomes harder to reason about over time.
Technically, the system still functions. Organizationally, it begins to seize. Every change requires cross-team coordination. Every incident triggers a war room. Every new compliance requirement becomes a multi-quarter platform fork.
This is the pressure that drives the next architectural evolution.
These problems demand an architecture where fleet-level isolation is not a property you add but a property you are born with. This is where cell-based architecture enters.
Cell-Based Architecture
Cell-based architecture is the answer to a specific question: how do you make fleet-level failure isolation a first-class architectural primitive?
CBA should feel inevitable, not novel.
The idea is simple: partition your entire infrastructure into fully isolated, self-contained units called cells. Each cell is a complete copy of your stack - compute, database, networking, queues - serving a defined slice of your customers. Cells do not share infrastructure. They do not share deployment pipelines. They do not share failure domains.

If Cell A goes down, Cells B, C, and D are completely unaffected. If you deploy to Cell A first, you validate the change on 10% of customers before touching the rest. If the deployment goes wrong, your blast radius is exactly one cell.
This is not a new idea. Companies like Stripe, Slack, and DoorDash have all converged on similar patterns. The convergence is not coincidence - it is the natural outcome of the same operational pressures.
What Is a Cell?
A cell is a fully self-sufficient deployment of your product stack. It contains everything a subset of customers needs to operate independently:
| Component | Definition |
|---|---|
| Cell Router | The only global entry point. On each request, it looks up the tenant-to-cell mapping and forwards deterministically. Typically a thin, stateless service or API gateway configuration. |
| Cell | An identical clone of your full application stack - compute, database, caches, queues - for its assigned tenants. Cell size is determined by your operational model (e.g. 500 tenants per cell, or by usage tier). |
| Control Plane | A management layer that knows about all cells. Handles provisioning, deployments, health monitoring, scaling, and cell lifecycle management. |
| Global Metadata Store | A small, highly-available database separate from any cell. Stores only the tenant-to-cell mapping, auth tokens, and billing state. The router reads this on every request. |
The key property is that cells are hermetic. They do not communicate with each other. Cross-cell requests are architecturally impossible by design. This is what makes the isolation guarantee reliable - it is not enforced by policy, but by topology.
Hermetic isolation means deployment, failure, and scaling are all cell-local. This yields concrete benefits across the entire operational lifecycle.
The cell boundary is a one-way door
Once you define what lives inside a cell, you're commited. Changes to this design, once deployed, means redeployment of cells, which can be REALLY EXPENSIVE!
1. No borrowing or fallback available
If a service inside a specific cell crashes, then there is no redundancy within that cell. The customer within that cell lose that service. We cannot route those request to the service from another cell. That would violate the isolation boundary. The cell must be self-sufficient or it's broken.
This is basically different from actual microservice wherein a failing service can be routed around. In CBA, the cell boundary is a hard-wall. What's inside must be complete. One mitigation we can create is to add redundancies and fail-safes inside the boundary, which again increases the cost of managing and operating the cell.
2. The "what goes inside the cell" decision is irreversible at scale
If you decide Identity lives outside cell (at L1/global), every cell depends on a shard service, and you've re-introduced a fleet-wide blast radius for auth-failures.
I've been in a HOT/Incident room (Sev 1) where the identity service went down, leading to complete collapse of authorisation requests throughout the infrastructure. Note that this problem is not specific to Cells, but if we are keeping auth outside as global service, we need to understand the side-effects of that decision.
If we decide Identity lives inside the cell, you now have copies of identity to maintain and the cross cell operation (what if the user can belong to multiple orgs? wouldnt that cause data replication?!), which were already complex, now become a nightmare to work on architecturally.
Neither Choice is right or wrong, but both will be permanant. Like I said before, we cannot easily move a service from cell-local to global or vice versa once tenants are running.
3. Internal failure modes get complex
In a non-cell world, if your DB hits a connection limit, you can fail over to a read replica, perhaps in another AZ, or load-shed to another instance. Inside the cell our options are bounded, thus our cell-internal architecture must be over-engineered for resilience. Because there is no help coming from outside the cell. That means:
- More Replicas
- Faster Failovers
- Tighter Circuit Breakers
4. Cell design is Fleet Design
Each cell is created from a blueprint called archetype. Think of it as a way to specify what each cell contains, including services, connections, permissions, replications, configurations, and a lot more. A flaw in this archetype will propagate itself in the whole fleet. For example if we under-provision the DB connection pool in the archetype, every cell will have the same ceiling. If we forgot to have a caching layer, no cell have one (a scary thought!).
Remember, Blueprints are expensive to change once your city is already bustling with people and traffic.
Benefits of CBA
Because deployments are cell-local, blast radius shrinks naturally. Because cells are stampable, regulated environments become composable. Because cells are independent, capacity planning becomes predictable.
Fault isolation - A cell failure affects only its tenants. No cascading failures across the fleet.
Predictable scaling - Add capacity by adding cells. Each cell has known, bounded resource usage.
Safe deployments - Deploy cell-by-cell. Validate on 10% before rolling to 100%. Rollback is a cell-level operation.
Tenant isolation - No noisy neighbors. Each cell's resource envelope is fixed.
Compliance composability - A validated cell pattern can be stamped into any regulatory perimeter.
But isolation at this level comes with real costs - operational complexity that every team must be prepared to absorb.
The Cost of CBA
You are now operating a distributed fleet OS. The operational complexity of N databases, N deployment pipelines, and N observability stacks is real.
Cross-cell queries are impossible by design - running analytics across your entire dataset requires an ETL pipeline that aggregates from all cells into a data warehouse. Cell migrations (moving a tenant from one cell to another) inherited all the difficulty of shard migrations, now applied at the fleet level.
For most B2B SaaS companies, the crossover point where cells become worthwhile is somewhere around 100–500 paying customers. Before that, a well-structured monolith with good tenant isolation is the right call.
If you have fewer than 100 customers, or your operational tooling is not mature enough to manage multiple independent stacks, CBA will slow you down. The architecture solves problems you don't yet have.
While costs are real, one domain where CBA's isolation pays for itself many times over is regulatory compliance - where cells transform platform forks into topology stamps.
Things That Don't Fit Into Cells
Cells promise hermetic isolation. But the moment you have a real product, you discover that some concerns are inherently cross-cell.
Billing Aggregates across a customer's entire footprint
A customer's bill is the complete sum of usages for all their workloads, which may span multiple cells if they have multiple products or multiple sites. Billing state is org-scoped, not cell scoped.
Identity & Authentication
A user logs in before you know which cell their org lives in. the auth check itself cant live inside the destination cell, You need it before routing. Same for SSO Sessions, MFA state and account level operations.
Abuse Detection (needs a fleet-wide, company-wide detection)
Any bad actor distributing request across cell can look fine from inside any cell. But from outside, the pattern will be visible.
Entitlements & Licensing
Whether a customer is on the Premium plan is a fact about the customer, not about any one cell. If you replicate them into every cell, you need a distributed agreement protocol to update plans, which is crazy, but also the cross cell coordination, we are trying to avoid.
Analytics & Data Warehousing
You cant run cross-tenant analytics from inside a cell. Building a usage dashboard for the company require ETL pipelines that aggregate every cell data into a different analytical store.
The Observablity Control Plane
We need to have a Dashboard/s that looks across all the cells and provides us with charts, alerts, on-call routing to be useful. Per-Cell dashboards are not as good. A better way is to add a X-Cell-Id to drill-down on per-cell metrics!
CBA doesn't eliminate these, it rather forces you to name, isolate and design them deliberately as a separate tier. Now comes the real twist! CBA isnt "everything lives in a cell". Its a Two-Tier Architecture where most things (archetyped) live in cells, and a small carefully bounded set of services, live above them (as in providing service to all the cells).
The Iterative Adoption Path
Now that we have a general idea on what and how a CBA is. Lets talk about how or when should we consider this architecture. (The Burning Question everyone might have at this point).
Cells are a destination and not a starting point. Using it from Day 1 is over-engineering. But building a system that cannot evolve towards cells is a different kind of mistake, which will require a "Refactor" type of application migration, in which we need to recreate working system from ground up in order to ensure that extra items and in-place isolation logic is removed.
Think of a multi-tenant SaaS using distributed database, and for each tenant they filter tenant_id for retriving their records.
Not only the SQL logic will be redundant had it been in cell. But also the way optimizations were done in order to ensure that any other tenant is not hogging resources.
Now all the resources in a cell will belong to this tenant (assuming we go one cell per org/client). In that case we might also need configuration to tweak resource allocation based
on tenant's usage. (all these discussions need to happen, while creating the archetype).
TL;DR : The cost of "cell-ready" design is small, The cost of retrofitting a system that wasnt designed for it is enormous.
Stage 1: Tenant Context in Every Request
This matters because, every later stage (sharding, routing, cells) require this. Retrofitting it across a codebase that "has" or "knew" the tenant from the session state / URL parsing is one of the most painful migrations engineer ever will have to undertake. And I pray for you if you are the unlucky person doing it. Doing it from day 1, costs almost nothing.
Stage 2: Pick a Sharding Key (Even if you dont Shard yet)
You may (currently) have one database and one deployment, which is a good starting point. But ask:
If I had to split this in per-tenant way what would i split on? What would provide our customers/tenants most benefit?
The answer should be in form of Org, Workspace, Region, Customer Tier, or something else entirely based on your requirement.
Then start writing code for it:
- Queries scope by sharding key (No Cross Tenant
SELECT * FROM customer_tableallowed - API Require
X-Sharding-KeyorX-Sharding-Idor whatever you wanna call it. - Background jobs are partitioned by your key
- Caches are keyed (important, we dont wanna send stored data of a Tenanted Hospital application to that of a Tenanted Jail System.
You are not building shards, rather a system that could be sharded without "ReWrite"-ing the data access layer.
Stage 3: Service-Level Sharding
Shard the services which are hitting the scaling wall. And use this migration experience as a template. Still, at this point you dont need cells. What you need is to split overloaded databases, and noisy services, and Queues. Use the routing key you selected in stage 2 to route your traffic.
But while you're at it create a pattern:
- A
Tenant-To-Shardlookup service (even if there is only 2 shards) - A routing layer that hides shard topology from consumers.
- Per shard observablity (as said earlier)
- Perhaps, a migration tool to automate this!
Stage 4: Standardize on One Routing Key Across Service
Standardize on one routing key across services. This is the turning-point! By now you should have atleast 3-5 sharded services, and each picked the key that was easiest for them.
For Example: One uses orgId, another uses workspaceId while the third uses customerId.
!!!! STOP !!!!
Pick one key that all the service will align to. Migrate service to as they need re-architecting. This is slow-work, but needs to be done. Either Proactively or reactively.
Atlassian learned this the hard way. After years of sharding , services had drifterd into different keys, and converging them became one of the largest costs of CBA Adoption.
Stage 5: "It's Alive..." Your First Cell
Most of the companies stop before reaching here. But if you are able to scale upto this. Dont build cells "for the future". BUild the first cell when you have real present need:
- A regulated customer who needs data isolation (FedRAMP, sovereignty)
- A Geographic Expansion that requires a separate region
- A noisy enterprise customer who needs dedicated capacity Try to find a custom usecase (not all cell based architectures are same). It should cater to your immediate needs.
Stage 6: Cell Fleet
Now you're at a LARGE COMPANY Problem. Build the platform: Cell Hydration, Archetype management, Tenant Placement, Service Migration Tooling, Observablity across cells. This is Years of work.
The Decision Framework
A simple test when to move to the next stage:
| Step | Explanation |
|---|---|
| Stage 1 → 2 | When you have more than one service that needs to know about tenants. |
| Stage 2 → 3 | When one service genuinely cannot scale further without sharding. |
| Stage 3 → 4 | When you have more than two sharded services and they're drifting. |
| Stage 4 → 5 | When you have a customer or compliance requirement that single deployment cannot satisfy. |
| Stage 5 → 6 | When you have more than one cell and managing them manually has become a bottleneck. |
CBA, GovCloud, and Regulatory Boundaries
This is where CBA becomes transformational rather than merely useful.
Before CBA, onboarding a regulated environment - GovCloud, FedRAMP, IL4/5, IRAP, C5 - was treated as a massive one-off engineering initiative. Each new compliance target required its own platform fork, its own deployment model, its own audit process. The result was predictable:
- Commercial environments evolved rapidly while regulated environments stagnated
- Features available in commercial clouds never reached regulated tenants
- Engineering teams built environment-specific logic
- Architectural entropy accumulated
"CBA turns compliance from a platform fork into a deployment topology problem."
The shift is profound. Once a cell pattern is validated, it can be reproduced consistently across clouds, sovereign environments, and regulatory perimeters. The cell becomes a stampable and repeatable deployment primitive.
Instead of creating bespoke regulated platforms, teams stamp standardized cells into different trust perimeters while preserving operational consistency and architectural parity.
CBA enables a true "Build Once, Deploy Everywhere" capability - compliance becomes a deployment topology decision rather than a platform rebuild.
Feature Enablement in Regulated Environments
In regulated systems, deployment is not purely an engineering concern - it is a governance and compliance workflow. CBA changes the deployment model entirely by treating regulated environments as isolated, reproducible cells rather than special-case platform forks.
Standard artifact promotion becomes a structured, traceable pipeline:
- Snapshot generator detects newly produced artifacts
- Artifacts are normalized into structured deployment snapshots
- Release manager pulls approved snapshots for the regulated environment
- Artifacts are replicated into quarantine storage
- Automated and manual compliance review is executed
- Approved artifacts are promoted: Quarantine → Trusted Artifact Storage
- Release manager triggers deployment pipelines
- Deployment occurs independently per cell
The result is that the same deployment primitives operate across both commercial and regulated environments - with stronger isolation guarantees where needed, but without requiring a fundamentally different architecture.
The shift from monoliths → microservices → shards → cells is the story of isolation boundaries becoming more fundamental. CBA is not the end - it is the current frontier.
Final Thoughts
The evolution from monoliths → microservices → shards → cells is fundamentally the evolution of isolation boundaries.
Each step partitions a larger shared system into smaller, more independent units. Each step trades operational simplicity for safety at scale. Each step becomes necessary when the cost of shared fate exceeds the cost of partitioning.
CBA is not the end of this evolution. It is the current answer to a specific class of operational pressure. As systems grow larger and compliance requirements become more complex, the isolation boundaries will continue to shift. But the direction is clear: architectures that make isolation a first-class primitive will consistently outperform those that treat it as an afterthought.
The goal is not to build systems that never fail. It is to build systems where failure is contained, understood, and recoverable - by design.
If CBA gives us fleet-level isolation, what does that mean for how we design security and compliance frameworks? The same isolation primitives that contain failure domains also create natural trust boundaries - enabling a cell-native Security Reference Architecture where attestation, authorization, and audit are properties of the topology, not bolt-on afterthoughts. That's the subject of the next essay.