Cell-Based Architecture

Cell-based architecture (also called cellular architecture or, in Microsoft’s terminology, stamps architecture) is a pattern in which a system is composed of multiple independent, self-contained replicas of the entire stack — each replica called a cell or stamp — where each cell handles a bounded subset of users, tenants, or workloads. AWS gives the canonical definition: “A cell-based architecture uses multiple isolated instances of a workload, where each instance is known as a cell. Each cell is independent, does not share state with other cells, and handles a subset of the overall workload requests” (AWS Well-Architected, What is a cell-based architecture?). The mental anchor AWS uses is the bulkhead of a ship: vertical partition walls subdivide the hull into self-contained watertight compartments, so a hull breach floods one compartment rather than sinking the ship. The defining property is that failure of one cell does not affect any other cell: a cell is a blast-radius unit, not just a deployment unit. Each cell contains the full vertical of services and data needed to serve its assigned subset; a thin cell router in front directs each request to the cell owning that request’s subject by a partition key (typically tenant ID, customer ID, or resource ID) and “presents a single endpoint to clients.” The pattern emerged from operational experience at AWS, where the canonical references are the AWS Builders’ Library article “Workload isolation using shuffle-sharding” (AWS Builders’ Library) and the AWS Well-Architected guidance “Reducing the Scope of Impact with Cell-Based Architecture” (AWS Well-Architected). It has been adopted by Slack (who migrated their critical user-facing services from a monolithic to an availability-zone-scoped cellular deployment over about 18 months, Slack Engineering 2023), Salesforce (whose multi-tenant “pods” predate the formal “cell” terminology by more than a decade), and others. The interview-relevant gravity is that cell-based architecture is the operational pattern teams reach for after monolithic-deployment failures have demonstrated, painfully, that the blast radius of a single deploy was the whole product — turning every deployment into a coin flip with the entire customer base on the losing side. By contrast, in a cellular system a bad deploy or runtime bug touches only the cells receiving the change, leaving the rest of the customer base unaffected.

The terminological landscape around cells, stamps, deployment units, and shards is muddled because the same idea has been independently rediscovered by multiple companies under different names. This note uses cell as the primary term (matching AWS’s terminology), but be aware that “stamp” (Microsoft Azure), “pod” (Salesforce, predating Kubernetes Pods), and “shard” (when used at the deployment-unit granularity rather than the data-partition granularity) often refer to the same architectural primitive. AWS decomposes the architecture into exactly three named components — the cell router (“the thinnest possible layer, with the responsibility of routing requests to the right cell, and only that”), the cell (“a complete workload, with everything needed to operate independently”), and the control plane (“responsible for administration tasks, such as provisioning cells, de-provisioning cells, and migrating cell customers”) — and this three-part decomposition is the cleanest way to reason about the pattern.

When to Use / Not Use

Use cell-based architecture when:

  • The operational cost of a system-wide outage is unacceptable. A payment processor going down for thirty minutes is a different kind of incident from a marketing site going down. Cells let the team trade a small increase in operational complexity for a dramatic reduction in worst-case blast radius.
  • Workloads naturally partition by tenant, user, or workload class. SaaS products with thousands of customer organizations, multi-region services where users are bound to a region, or workload mixes where batch jobs and online traffic can be cleanly separated all admit cellular boundaries.
  • You have already experienced the “every customer affected” failure mode. AWS’s S3 outage in February 2017, Slack’s January 2021 outage, and many others share a common postmortem: a fleet-wide deployment or a fleet-wide configuration change brought down the entire system. Teams that have lived this pain are far more willing to invest in cellular structure.
  • Regulatory or sovereignty requirements force isolation. Financial-services compliance, healthcare HIPAA, EU GDPR data-sovereignty, and similar regimes often mandate that certain customer cohorts be isolated from others; cells are a natural way to encode the isolation in the architecture.
  • You need to support customers at very different scales on the same platform. A SaaS product whose top customers are 100× the size of typical customers can put each “very large” customer in its own cell, isolating their load from the shared pool.

Avoid cell-based architecture when:

  • The system is small enough that one production deploy is the entire system. A startup with fifty engineers serving 1000 customers does not need cells; the operational cost dwarfs the failure-isolation benefit.
  • Cross-customer features are central to the product. A social network’s “find friends across all users” feature, a multi-tenant analytics product’s cross-tenant aggregation features, or any product where customers fundamentally interact with each other will fight cell boundaries every step of the way.
  • You can solve the problem more cheaply with deployment hygiene. Many of the failure modes cell-based architecture protects against can also be addressed with progressive deployment (canary, blue-green), feature flags, and circuit breakers. If those are insufficient, then consider cells.
  • The team lacks the operational maturity for N-times-the-cluster operations. Cells multiply every deployment, every observability dashboard, and every incident response by N. A team that struggles to operate one production cluster will struggle exponentially more with ten.

Structure

flowchart TB
    subgraph "Edge"
        DNS[DNS / Anycast]
        ROUTER[Router / Cell Mapping<br/>tenant_id -> cell_id]
    end
    subgraph "Cell 1 (tenants A,D,G,...)"
        APP1[Application Services]
        DATA1[(Data Stores)]
        CACHE1[(Cache)]
        OBS1[Observability]
    end
    subgraph "Cell 2 (tenants B,E,H,...)"
        APP2[Application Services]
        DATA2[(Data Stores)]
        CACHE2[(Cache)]
        OBS2[Observability]
    end
    subgraph "Cell 3 (tenants C,F,I,...)"
        APP3[Application Services]
        DATA3[(Data Stores)]
        CACHE3[(Cache)]
        OBS3[Observability]
    end
    subgraph "Shared (minimal)"
        IAM[Identity / SSO]
        BILL[Billing]
        META[Cell Mapping DB]
    end
    DNS --> ROUTER
    ROUTER --> APP1
    ROUTER --> APP2
    ROUTER --> APP3
    ROUTER -.read.- META
    APP1 --> IAM
    APP2 --> IAM
    APP3 --> IAM
    APP1 --> BILL
    APP2 --> BILL
    APP3 --> BILL

What this diagram shows. Three independent cells, each containing the full vertical stack: application services, datastores, caches, and observability. A small shared layer at the bottom holds the truly cross-cell concerns: identity (because users authenticate once and need a single login), billing (because the company aggregates per-tenant usage across cells), and the cell-mapping registry that the router consults to know which cell owns which tenant. The router at the top — DNS, anycast, or a thin routing service — performs the tenant-to-cell mapping: it reads the request’s tenant identifier (from the URL subdomain, an authenticated session, or an explicit header), looks up which cell owns that tenant, and forwards the request.

The key insight is the vertical isolation: each cell has its own database, its own cache, its own application servers, its own deployment pipeline. A bug deployed to cell 1 affects only the tenants assigned to cell 1; cells 2 and 3 keep running unmodified. Compare this to a sharded-storage architecture where the application servers are shared across all shards — in that model, an application bug brings down all customers regardless of which database shard they live on. Cells push the isolation boundary up the stack to include the application code, eliminating that failure mode.

The shared layer at the bottom is a deliberate compromise. Pure cellular purity would have zero shared services; in practice, identity and billing are too central to the product experience to fragment, and the cell-mapping registry is the canonical “where does each tenant live” data. The discipline is to keep the shared layer minimal and to architect each shared service so that its outage does not take down the cells (e.g., the cell mapping is cached aggressively, IAM has long-lived sessions, billing is async and batched). When the shared layer goes down, the cells continue serving authenticated existing-session traffic.

A second key property is that cells can be deployed independently and asynchronously. A deployment is rolled out cell-by-cell in waves: cell 1 gets the new version, the team monitors for problems for an hour, cell 2 follows, and so on. A bad deploy is caught after one cell’s tenants experience the issue; the remaining cells are unaffected. The pattern trades faster, all-at-once deployments (everyone gets the new feature within minutes) for safer, slower deployments (everyone gets the feature within a day, but if it’s broken only one cell sees it).

Core Principles

Each cell is fully self-sufficient. A cell can serve its tenants’ traffic with no runtime dependency on other cells. This is the single most important property; if cell 1 cannot serve its traffic without calling cell 2 or cell 3, the cells are not actually independent.

  • The cell contains its own copy of all stateful services it needs.
  • Inter-cell communication is restricted to the shared layer (identity, billing) plus async events (cross-cell aggregation for analytics).
  • A cell’s deployment, scaling, and incident response are owned by the cell, not by some global controller.

Failure of one cell does not affect others. This is a testable property: if you can intentionally fail cell 1 in production and tenants on cells 2–N see no degradation, you have cell isolation. If cell 1’s failure causes any user-visible degradation in cell 2 (e.g., shared cache thrash, shared identity service overload, cross-cell calls timing out), the architecture is not cellular in the strong sense.

  • Operational drills (chaos engineering at the cell level) verify this.
  • Cells should not share connection pools, message queues, or critical-path data stores with other cells.
  • Even at the network level, cells often have separate VPCs or subnets to prevent network-level blast.

Cells are sized for predictable failure isolation. A cell that is too small means too much operational overhead per cell; a cell that is too large means a cell failure still affects too many customers. AWS’s Cell sizing guidance frames this as three opposing forces: a cell must be “big enough to fit the largest workloads,” “small enough to test at full scale (and to operate efficiently) … below the AWS account limits,” and “big enough to gain economies of scale benefits” (AWS Well-Architected, Cell sizing). Crucially, AWS does not prescribe a fixed percentage; it explicitly states “the maximum cell size will vary per-service” and that the optimum “needn’t be extremely large for any service.” The percentages that float around — “10 cells, each one has 10% of their customers; with 100, each one has 1%” — are AWS’s illustration of how blast radius shrinks with cell count, not a recommended target. The right size is instead derived from a concrete capacity ceiling per cell: how many transactions per second, how many tenants, or how many gigabytes per second a single cell can absorb before risking a scaling cliff. The trade-off is therefore between operational overhead (more cells = more replicas to manage) and blast-radius granularity (more cells = smaller percentage hit per failure), with the floor set by economy-of-scale and the ceiling set by testability and account/service quotas.

Uncertain

Verify: that “AWS recommends 5–10% of total load per cell.” Reason: the primary AWS Cell sizing page gives no such recommendation — it uses 10%/1% only as an illustration and says cell size is service-specific, bounded by per-cell capacity limits and account quotas. The earlier draft of this note stated the 5–10% figure as AWS guidance; that framing has been corrected here and removed elsewhere. To resolve: this is resolved against the primary source; the figure should not be cited as AWS guidance.

Cell-to-tenant mapping is sticky. Once a tenant is assigned to a cell, they stay on that cell for the long term. Migration between cells is possible but expensive and disruptive (data migration, cache warmup, in-flight request handling). The mapping is updated rarely.

  • Initial assignment is by hash of tenant ID, by enrollment cohort, or by explicit business logic (large customer goes to a dedicated cell).
  • Re-balancing is an operational project, not a runtime decision.
  • This stickiness contrasts with stateless load-balancing where any request can go to any backend.

Cells share the minimum viable cross-cutting infrastructure. Identity, billing, cell-mapping, and possibly cross-cell analytics are shared. Everything else is per-cell.

  • The shared layer’s outage budget is much tighter than any individual cell’s, because it affects all cells.
  • Shared services should be designed with extreme care: heavy caching, async batching, fall-back behavior when the shared service is down.

Shuffle-sharding (optional but powerful refinement). AWS’s shuffle-sharding pattern (AWS Builders’ Library on shuffle-sharding) extends cellular isolation by assigning each tenant a combination of cells rather than a single cell. With N workers (or cells) and a shard size of K, each tenant uses K out of N, drawn as if dealing a hand from a shuffled deck — hence the name. The number of distinct shuffle shards is the binomial coefficient C(N,K) = N! / (K!·(N−K)!). The Builders’ Library’s worked example: with 8 workers and a shard size of 2, “there are 28 unique combinations of two workers, which means that there are 28 possible shuffle shards,” so a single misbehaving tenant’s problem hits “just 1/28th” of the fleet — “7 times better than regular sharding” (which with 8 workers in 4 fixed shards exposes one quarter of customers). The key invariant is that two tenants’ K-sets overlap partially at most with high probability: “at most one of another shuffle shard’s workers will be affected” when one tenant is under attack. The canonical production case is Amazon Route 53, which uses 2,048 virtual name servers with shuffle shards of size 4 — “a staggering 730 billion possible shuffle shards” — engineered so that “no customer domain will ever share more than two virtual name servers with any other customer domain.” The intuition behind the name is the card-deck analogy AWS uses elsewhere: dealing a four-card hand from a deck has over 300,000 possible outcomes, so re-dealing the same hand is vanishingly unlikely — the same rapidly-diminishing collision probability that makes full overlap of two shuffle shards combinatorially rare (AWS Architecture Blog, Shuffle Sharding: Massive and Magical Fault Isolation).

Request Flow

sequenceDiagram
    participant USER as Browser
    participant DNS as DNS / Edge
    participant ROUTER as Cell Router
    participant MAP as Cell Mapping DB
    participant CELL2 as Cell 2 App
    participant DB2 as Cell 2 Database

    USER->>DNS: GET acme.app.com/orders
    DNS-->>USER: A record (anycast IP)
    USER->>ROUTER: HTTPS request, Host: acme.app.com
    ROUTER->>MAP: which cell owns tenant "acme"?
    MAP-->>ROUTER: cell_id=2 (cached after first lookup)
    ROUTER->>CELL2: forward request
    CELL2->>DB2: query orders for tenant "acme"
    DB2-->>CELL2: results
    CELL2-->>ROUTER: response
    ROUTER-->>USER: response
    Note over MAP: Mapping is sticky;<br/>changes are rare ops events

Walk-through. A user navigates to acme.app.com. DNS resolves to the cellular router’s IP (often anycast, so the user hits the geographically nearest router). The user makes the request; the router extracts the tenant identifier — here from the subdomain acme — and looks up the cell mapping. The mapping is cached aggressively because it changes rarely; for a hot tenant, the lookup is essentially free. The router forwards the request to the application servers in cell 2, which serve it from cell 2’s database. The response goes back through the router (or directly, depending on design) to the user.

The crucial property is that at no point in the synchronous request path is there a call to any other cell. Cell 2’s database is local to cell 2; the user’s session lives in cell 2’s cache; the application code running in cell 2 is the only code that touched the request. If cell 1 is on fire at this moment, the user notices nothing.

The cell mapping lookup is the most performance-sensitive part of the architecture. If every request must do a fresh lookup, the mapping service becomes a hot path with availability requirements stricter than any individual cell. The standard approach is to make the mapping service a cache-friendly read-mostly store (DynamoDB Global Table, Spanner, or even a static config file) and to cache the mappings at the router with long TTLs. Updates to the mapping (cell rebalancing, new tenant onboarding) propagate within minutes, which is acceptable given how rarely they happen.

A common refinement is to have the cell identity baked into the URL or session token directly, so the router can route without consulting the mapping at all. For instance, a JWT issued at login time can encode the cell ID; the router reads the JWT and routes by its claims, no mapping lookup needed. This eliminates the mapping service from the synchronous path entirely.

Variants

Region-as-cell. Each AWS region (or GCP region, or Azure region) is a single cell. A regional outage affects only the tenants assigned to that region. This is the granularity used by many SaaS products that already have regional deployments — the cellular structure falls out of the regional structure for free.

  • Fewer cells (3–10 for a global product) but each is large.
  • Combines naturally with Multi-Region Active-Active Architecture.
  • Limits blast radius to “one region’s worth of customers” — sometimes still too many.

Availability-zone-as-cell. A finer granularity within a region: each cell is an AZ. AWS internal services often use this when they want to tolerate AZ failures without cell failures (the cell is the AZ; an AZ failure means the cell fails, but the system continues on other-AZ cells).

  • More cells (3 per region × number of regions), each smaller.
  • Tight coupling to underlying cloud topology.
  • Useful when AZ-level fault domains map cleanly to operational reality.

Sub-region cells (multiple cells per AZ). Even finer granularity — each cell is a deployment within an AZ, with multiple cells coexisting in the same AZ. This is what AWS’s largest internal services often look like.

  • Many small cells (tens to hundreds).
  • Cells within an AZ share infrastructure failures (an AZ outage takes them all down) but isolate against application bugs and configuration errors.
  • Highest blast-radius control but highest operational overhead.

Tenant-cell vs workload-cell. Cells can be partitioned by tenant identity (acme.com → cell 2) or by workload type (online traffic → cell A, batch jobs → cell B). The two flavors solve different problems.

  • Tenant cells protect against cross-tenant noisy-neighbor and per-tenant failure isolation.
  • Workload cells protect against batch workloads disrupting online traffic.
  • The two compose: a system can have tenant cells for online traffic and a separate set of workload cells for batch.

Dedicated cells for large customers. A common pattern in B2B SaaS: most customers share pooled cells, but the largest enterprise customers each get a dedicated cell. The economics work because the large customer pays enterprise pricing that justifies dedicated infrastructure.

  • Pooled cells handle the long tail of small/medium customers efficiently.
  • Dedicated cells give large customers contractual isolation for compliance, performance, and SLAs.
  • The router uses different mapping logic for “in pool” vs “dedicated” tenants.
  • Combines naturally with Multi-Tenant Architecture tenancy levels.

Shuffle-sharded cells. Each tenant is assigned a subset of K cells out of N, with requests distributed across the subset, combining cellular isolation with the combinatorial blast-radius properties of shuffle-sharding described in the Core Principles. This is mathematically robust to single-tenant catastrophic load — a tenant that takes down all of its K cells very rarely fully overlaps another tenant’s K-set — at the cost of more complex routing and consistency logic, because a request for a given tenant can land on any of its K cells. The production exemplar is AWS Route 53’s data plane, which uses 2,048 virtual name servers in shuffle shards of size 4 (730 billion combinations, no two customers sharing more than two name servers), giving DDoS resilience: an attack saturating one customer’s four name servers leaves essentially every other customer with at least two unaffected name servers (AWS Builders’ Library).

Real-World Examples

Amazon Web Services. The cellular pattern was developed and refined inside AWS over more than a decade and is now formally documented in the AWS Builders’ Library and the Well-Architected guidance “Reducing the Scope of Impact with Cell-Based Architecture.” A frequently cited cautionary tale is the February 28 2017 S3 disruption in us-east-1: an S3 team member running a standard capacity-removal procedure “entered [one of the inputs] incorrectly and a larger set of servers was removed than intended,” which knocked out the S3 index subsystem (holding “the metadata and location information of all S3 objects in the region”) and the placement subsystem, taking down GET/LIST/PUT/DELETE region-wide and cascading into EC2 launches, EBS, and Lambda (AWS — S3 service disruption summary, 2017). The lesson cellular advocates draw is that an operation scoped to one cell, with the same fat-fingered command, would have removed capacity from only that cell rather than the whole region’s metadata fleet. Concretely, Route 53’s data plane uses shuffle-sharded cells for DDoS resilience (the 2,048-virtual-name-server design above); DynamoDB’s data plane is internally cellular at multiple levels; and Lambda’s invoke frontend is cellular to bound the blast radius of frontend failures. The Well-Architected guidance now formalizes the patterns AWS uses internally.

Slack. Slack documented their cellular migration in a 2023 engineering blog post, “Slack’s Migration to a Cellular Architecture” (Slack Engineering 2023). The published motivation was not the well-known January 4 2021 global outage (whose root cause was AWS Transit Gateway saturation and packet loss, triggered by a cold-cache traffic spike on the first Monday back after the holidays — the Transit Gateways failed to autoscale fast enough, per Slack Engineering’s Jan 2021 postmortem). The cellular migration was instead driven by a June 30 2021 incident in which a network disruption in a single US-East availability zone caused user-visible errors that the cloud’s per-AZ fault isolation should in principle have contained. The culprit was a gray failure: “in a gray failure, different components have different views of the availability” of the system, so automatic failure detection did not fire cleanly — a single shard primary becoming unreachable could block all writes to its data while health checks still passed.

Critically, Slack’s cell boundary is the availability zone, not the region: each service “appears to be N virtual services, one per AZ,” and siloing means services “only receive traffic from within their AZ and only send traffic upstream to servers in their AZ,” preventing cross-AZ cascades. The operational lever this buys is AZ draining: using Envoy load balancers configured by Rotor (Slack’s in-house xDS control plane) via weighted clusters and the Runtime Discovery Service (RTDS), Slack can reweight an AZ’s traffic — including all the way to zero, at 1% granularity — so that in-flight requests complete while all new requests shift to healthy AZs. The design goal was to drain a bad AZ within 5 minutes, which is what their 99.99% availability SLA (under one hour of unavailability per year) requires. The migration of critical user-facing services took about 1.5 years. Cross-cell features (search across cells, organization-wide federation) are handled by an asynchronous cross-cell plane rather than synchronous cross-AZ calls.

Salesforce. Salesforce has long run a “pod” (also called instance or Point of Deployment) architecture, where a pod “is a self-contained unit that contains all that is required to run Salesforce, including the application server, database server, database itself, search and file system” (Salesforce CRM Administration Handbook). A pod groups on the order of 10,000 customer organizations, each customer is “allocated to one and only [one] POD and that is where their data resides,” and each pod sits within a geographical area (North America, Europe, Asia Pacific). This is essentially a cell — a full vertical stack serving a bounded subset of customers — and it pre-dates the formal “cell” terminology by more than a decade. The pod boundary is what lets Salesforce upgrade subsets of customers at different times, and customer migrations between pods (for capacity rebalancing) are a major operational endeavor. Note that within a pod Salesforce is multi-tenant: many orgs share the same database, with an org ID stamped on every row to keep tenants’ data separate — so the pod is a blast-radius cell wrapping a multi-tenant interior, the layered relationship discussed in the comparison with Multi-Tenant Architecture below.

Roblox. Roblox runs experiences in a client-server model where “the Roblox server is the ultimate authority for maintaining the experience’s state” and each running game world (a “place”) is served by its own game server; a new server is spun up when none is available or all are full (Roblox Creator Hub — Client-server runtime). The practical effect is per-game failure isolation: a misbehaving place affects only that place’s players, and cross-place features (friends, marketplace) live in shared services above the per-game servers. This is cellular-like at a domain-natural granularity (one cell per game session) rather than a documented tenant-cell architecture in AWS’s sense; Roblox does not publicly describe this as “cell-based,” so treat the framing as an analogy rather than an adopted pattern.

Uncertain

Verify: that Roblox’s per-place game-server isolation is deliberately a “cell-based architecture.” Reason: Roblox’s public docs describe a per-session client-server game-server model, not a named cellular/blast-radius architecture; the cellular framing here is the author’s analogy. To resolve: an official Roblox engineering write-up explicitly characterizing the model as cell-based would settle it.

Cloudflare. Cloudflare operates a single global anycast network in which “every server runs every service in every data center,” spanning data centers in over 330 cities (as of mid-2024) connected by 13,000+ network peers (Cloudflare — Global Network). Anycast routes each user to the nearest healthy data center; if a location fails, BGP withdraws its anycast advertisement and traffic shifts to neighboring locations. Each point of presence is therefore an independent full-stack unit — cellular in spirit, with the cell being an entire data center — though Cloudflare frames it as anycast plus run-everything-everywhere rather than the tenant-partitioned cell model AWS describes. It composes with Multi-Region Active-Active Architecture at the network level, and the per-POP independence is what makes a single location’s failure invisible to most users.

Stripe. Stripe’s payment infrastructure has evolved toward cellular structure as the company has scaled, with both regional and tenant dimensions: large enterprise customers may sit on dedicated infrastructure while pooled customers share regional cells.

Uncertain

Verify: the specifics of Stripe’s cellular structure (regional + tenant dimensions, dedicated vs pooled). Reason: Stripe has not published a dedicated cell-based-architecture write-up comparable to Slack’s or AWS’s; this characterization is inferred from general reliability/migration posts and is not pinned to a primary source naming the pattern. To resolve: a Stripe engineering post explicitly describing cellular/blast-radius isolation would settle it.

Tradeoffs

ChoiceProConWhen chosen
Many small cellsFine-grained blast radius, can isolate individual large tenantsHigh operational overhead, many deployment targetsMature platforms; AWS internal services
Few large cellsLow operational overhead, simpler topologyCoarse blast radius, single-cell outage affects more customersEarlier-stage cellular adoption
Region-as-cellAligns with cloud topology, no extra structureLimited to “region count” cells; coarseGlobal products with existing regional deployments
Sub-region cellsMaximum isolationMost complex; many deployment targetsAWS-scale internal services
Pooled cells (shared)Cost-efficient for small tenantsLimited isolation between pooled tenantsLong tail of small customers
Dedicated cellsPer-customer isolation, enterprise SLAsHigh cost per customerTop-tier enterprise customers
Shuffle-sharded cellsCombinatorial blast-radius boundingComplex routing, harder to reason aboutCritical-path services; large-scale platforms
Sticky cell assignmentSimple, predictableHard to rebalance load between cellsStandard
Dynamic cell assignmentFlexible load balancingRouting complexity, cache invalidationRare; requires extra mapping infra
Per-cell deploy wavesCatches bad deploys before fleet-wideSlower fleet-wide rolloutMature operational practice
All-cells-at-once deployFaster rollouts, simpler pipelineCell isolation does nothing for deploy bugsDeferring cellular discipline
Shared identity serviceSingle sign-on, central account modelIdentity outage affects all cellsStandard pragmatic compromise
Per-cell identityTrue isolation for identity failuresCross-cell login complexityRare; only when identity is critical-path

Migration Path

Migrating an existing non-cellular system to cellular is a non-trivial multi-quarter effort whose details depend heavily on the starting architecture. The dominant patterns in published case studies are:

  1. Establish the cell-mapping layer first. Before splitting any traffic, build the router and the cell-mapping registry. Initially the router maps everyone to “cell 0” (the existing system, treated as the first cell). This step gets the routing infrastructure into the request path so subsequent steps can split traffic without changing client-side configuration.

  2. Identify a cell boundary that fits the existing data model. The natural boundary is usually tenant ID, customer ID, or workspace ID. The boundary must be present at the start of every request — if some requests don’t carry the boundary identifier, those requests cannot be routed to a cell.

  3. Build a single second cell, identical to the existing system. This is the highest-leverage step: it forces every shared assumption out of the codebase. The first second cell is invariably an exercise in finding all the places where “the database” was assumed to be a single instance, where “the cache” was global, where deployment scripts hardcoded production hostnames.

  4. Migrate a small set of canary tenants to the second cell. Pick non-critical, internal, or volunteer tenants. Verify the routing, the data isolation, and the operational tooling work for these tenants. Iterate until the second cell is rock-solid for these canaries.

  5. Migrate progressively larger cohorts. Once the second cell is proven, migrate tenants in waves — perhaps 5 % at a time over weeks. Each migration involves data migration (copy the tenant’s data to the new cell), cutover (update the mapping), and verification (request flow continues working).

  6. Add additional cells as load demands. Once two cells exist, three is incremental work. The investment is front-loaded; the marginal cost of cell N+1 is much lower than cell 2.

  7. Make new tenants land on cells from day one. Once cellular structure is in place, all new tenants are assigned to cells via the mapping service from signup, eliminating the migration step for new customers.

  8. Refactor cross-cell features as async. Search across all tenants, organization-wide reporting, and similar features need to operate across cells. Build an async cross-cell layer (event streams, periodic aggregation jobs) that doesn’t synchronously call into individual cells.

The Slack 2023 blog post documents a multi-year version of this migration; AWS’s various services have done it over even longer time horizons. The migration is essentially never “done” — there are always shared services to push down into cells, always cross-cell features to refactor, always new patterns to absorb. The discipline is a long-term commitment, not a sprint.

Pitfalls

  1. Hot cell when one tenant gets disproportionate traffic. A tenant assigned to cell 1 launches a marketing campaign and brings 10× the normal traffic. Cell 1’s capacity is sized for normal load and cannot absorb the spike; cell 1 degrades while cells 2 and 3 sit idle. Mitigations are per-cell auto-scaling, dedicated cells for large tenants, and shuffle-sharding to distribute single-tenant load across multiple cells. Monitoring per-tenant traffic and proactively migrating large tenants to dedicated cells before they cause incidents is the operational discipline.

  2. Cell boundary leakage as features evolve. A new feature looks innocent: “show recommendations from across the user’s organization, including users on other cells.” Implemented naively, this means cell 1 calls cell 2 synchronously, and now cells 1 and 2 are coupled — the architecture has silently lost cellular isolation. The discipline is to route every cross-cell call through the async layer or refuse the feature; product pressure pushes against this discipline constantly.

  3. The operational tax of N-times-the-deployment. Every cell needs its own deployment pipeline, its own observability dashboards, its own incident-response runbooks. Tooling that works fine for one cluster (manual kubectl apply, manual log inspection) becomes intolerable across ten cells. Cellular architecture demands automation; without strong tooling investment, the operational burden grows linearly with cell count and crushes the team.

  4. The shared layer becomes the new monolith. Identity, billing, cell-mapping — the shared services accumulate features and become a critical path. An outage in the shared layer affects all cells, undoing the isolation benefits. The discipline is to architect the shared layer with extreme paranoia: heavy caching, fall-back behaviors, fast-fail semantics, and the smallest possible feature surface. Any shared service should be designed as if its outage budget is “zero seconds per year.”

  5. Cross-cell migration is expensive and disruptive. Moving a tenant from cell 1 to cell 2 involves data migration, cache warmup, in-flight request handling, and verification. For a tenant with terabytes of data, a migration is a multi-day operation. Teams that need to rebalance load frequently find this painful; teams that pre-allocate generously and migrate rarely fare better.

  6. Per-cell capacity headroom multiplies infrastructure cost. Each cell needs enough headroom to handle its peak; the total headroom across N cells is N times the per-cell headroom, vs a shared system where headroom is amortized across all customers. The cellular structure costs more raw capacity than a non-cellular structure for the same peak.

  7. Debugging cross-cell issues is painful. A user reports that something is broken; their request hit cell 2, but the pattern they’re describing involves data they think is in cell 3. Tracing across cells requires aggregated logging that respects cell boundaries — a significant observability investment. The “where is this user’s data?” question, trivial in a monolithic system, becomes a non-trivial query in a cellular one.

  8. Cell rebalancing is operational work, not automatic. When tenant load shifts (one tenant grows, another shrinks), the cells become unbalanced. There is no “auto-rebalancer” in most cellular systems; rebalancing is a deliberate human-driven project. The discipline is to plan for rebalancing as a recurring operational activity, not a one-time event.

  9. Cell-level deployment waves slow down release velocity. Deploying to cell 1, waiting an hour to monitor, deploying to cell 2, waiting another hour, etc., means a fleet-wide rollout takes most of a day. Teams used to “push to all customers in 5 minutes” find this frustrating. The trade — slower rollouts in exchange for safer rollouts — is worth it but requires culture change.

  10. Shared infrastructure failures still cascade. A cellular architecture protects against application-level failures but not against shared-infrastructure failures (the cloud provider’s regional outage, the DNS service failing, the BGP routing breaking). For full failure isolation, cellular structure must be combined with multi-region deployment (Multi-Region Active-Active Architecture) and with diversification of underlying infrastructure providers.

  11. Per-cell observability fragmentation. Each cell has its own dashboards. To answer “what is the system-wide error rate?” requires aggregating across cells. Without explicit per-cell observability tooling that supports aggregation, on-call engineers struggle to see the full picture during incidents.

  12. Underestimating the duration of the migration. Companies that have done cellular migrations almost universally report it took longer than initially planned. The hidden complexity is in the long tail — the dozens of shared assumptions buried in the codebase that surface only as specific edge cases trigger them. Budget at least 2× the initially estimated time.

  13. Cell identifiers leaking into customer-visible URLs. A naive implementation routes via subdomain like cell2.app.com, exposing the cell structure to customers. When a tenant migrates from cell 2 to cell 3, their URLs change — a breaking change. The discipline is to keep cell identity entirely server-side: customers see acme.app.com, the mapping service translates to a cell, the URL never changes. Cell identity is an internal implementation detail.

Comparison With Sibling Architectures

Versus Sharded Architecture. Sharding partitions data across nodes; cells partition the entire stack (services + data + deployment). A sharded system shares its application servers across all shards — an application bug brings down all customers regardless of shard. A cellular system has independent application instances per cell, isolating application bugs to a single cell. Cells are sharding pushed up the stack to include the whole vertical.

Versus Multi-Region Active-Active Architecture. Multi-region distributes traffic across geographic regions for latency and availability; cellular distributes traffic across deployment units for blast-radius isolation. The two compose naturally: cells can be regional (one cell per region) or sub-regional (multiple cells per region). Most large-scale architectures combine both axes.

Versus Microservices Architecture. Microservices is a service-decomposition pattern; cells are a deployment-unit pattern. A cellular system can host many microservices per cell; a microservices system can be cellular or not. The two answer different questions (“how do I structure my services?” vs “how do I bound my blast radius?”) and are largely orthogonal.

Versus Multi-Tenant Architecture. Multi-tenancy is about cost-efficient sharing of infrastructure across customers; cellular architecture is about blast-radius isolation. A cellular system is usually also multi-tenant within each cell (a cell hosts many tenants); a multi-tenant system can be cellular or not. The relationship is layered: multi-tenancy answers “how do I efficiently serve N customers?”, cellular answers “what is the blast radius of a failure?”.

Versus Monolithic Architecture. A monolith is the maximally non-cellular endpoint: one deployment, one process, one blast radius equal to the entire customer base. Cells push the architecture in the opposite direction: many deployments, many processes, many small blast radii. The two are opposite ends of a continuum, with sharded architectures and pooled multi-tenant architectures in the middle.

Versus Container Orchestration Architecture. Kubernetes is a runtime for cells, not a competitor. A cellular system might have one Kubernetes cluster per cell (strong isolation) or share clusters across cells via namespaces (weaker isolation, lower cost). The choice depends on whether the team can credibly argue that a Kubernetes cluster failure is rare enough to be an acceptable shared-infrastructure failure.

Worked Example: SaaS Company at 100K Customers — Single-Cell vs 10-Cell Architecture

Consider a SaaS analytics company at 100 000 customer organizations. The product serves dashboards, runs scheduled reports, and ingests customer data. The company is currently running a single-cell architecture: one production deployment, shared databases (sharded by tenant ID), shared application servers, shared cache. The question is whether to migrate to a 10-cell architecture.

Current state (single cell):

  • One Kubernetes cluster running ~50 microservices, deployed multiple times daily.
  • Sharded PostgreSQL: 32 shards by customer-ID hash, holding all customers.
  • Shared Redis caches.
  • Production incidents in the past year include three “all customers affected” outages: a bad deploy that crashed the API server fleet, a database migration that locked tables for 15 minutes, and a Redis cache invalidation bug that cascaded across all tenants.
  • Deployment cadence: ~30 deploys per day across the fleet.
  • Operations team: 12 engineers; product engineering: 80 engineers.

Proposed state (10 cells):

  • 10 Kubernetes clusters, each running the full microservice stack. Customers distributed roughly evenly: 10 000 customers per cell.
  • Each cell has its own PostgreSQL (sharded internally with 4 shards per cell, 40 shards total — fewer per cell because each cell holds less data).
  • Each cell has its own Redis.
  • Cell mapping registry holds tenant-to-cell assignments; router translates acme.app.com to cell N at request entry.
  • Identity, billing, and cross-cell aggregation are shared services.

Per-deployment cost analysis. Single cell: one rolling deployment touches all 100K customers in ~10 minutes; if the deploy is bad, 100K customers see degraded service until rollback. 10 cells with sequential wave deploys: deployment touches cell 1 first, monitored for one hour; if no issues, cell 2 follows; full fleet rollout takes ~10 hours. A bad deploy is caught at cell 1, affecting 10K customers (10 % blast radius) for the duration of the issue. The blast-radius reduction is 10× at the cost of 60× longer rollouts.

Blast radius analysis. Single cell: any of the three published incident classes affects 100K customers. 10 cells: a deploy-bug incident affects 10K customers (the cell currently being deployed); a database-migration incident affects whichever cell is being migrated (10K customers, plus the migration is no longer “all at once” so total exposure is bounded); a cache invalidation bug affects only the cell whose code rolled out the bug. The annual customer-incident-hours are reduced roughly 5–10× depending on incident class.

Operational complexity analysis. Single cell: one production cluster, one set of dashboards, one deployment pipeline. 10 cells: 10 production clusters, 10 sets of dashboards, 10 deployment pipelines (although deployable as a coordinated wave). Tooling must change: aggregated dashboards, cell-aware alerting, cross-cell incident response. The operations team needs to grow to roughly 18–22 engineers, an increase of 50–80 %, to operate the cellular system at the same maturity as the single-cell system.

Infrastructure cost analysis. Each cell needs its own infrastructure: 10 Kubernetes clusters (each smaller than the original single cluster), 10 Postgres deployments, 10 Redis deployments, 10 cell-router and observability stacks. Per-cell capacity headroom multiplies: each cell needs ~30 % headroom, so total headroom is 30 % × 10 = 300 % vs. 30 % in the single-cell case. Infrastructure cost increases roughly 25–40 %, depending on how much shared infrastructure remains.

Migration cost analysis. Initial migration is estimated at 9–12 months of focused engineering work: build the router, build the mapping service, refactor shared assumptions out of the application, build aggregated observability, migrate the first 10K customers in waves to validate the architecture, then migrate the remaining 90K customers in larger waves. Two senior engineers full-time + a rotating cast of contributors from product teams.

Recommendation matrix.

  • If the company’s customer-incident-hours are dominated by all-customer outages, the migration pays back within roughly 18 months in customer satisfaction and SLA-credit reduction.
  • If the company has rare outages and the operational cost matters more, single-cell with better deployment hygiene (canary, feature flags) might be a cheaper alternative.
  • If the company is growing rapidly toward 1M customers, cellular architecture is essentially mandatory — single-cell does not scale to that count without becoming operationally unmanageable.

Conclusion. For this company at 100K customers with a documented history of all-customer outages, the migration to 10 cells is a strong yes. The increased operational and infrastructure cost is justified by the order-of-magnitude reduction in customer-incident-hours and the more graceful scaling path to 1M customers. The migration is a multi-quarter effort, but it is the right architectural choice for this stage of the company.

Internals Deep Dive

The Cell Mapping Service

The cell mapping service — what AWS calls part of the cell router layer — is the single most performance- and consistency-critical piece of cellular infrastructure, because every request must resolve a partition key (tenant ID, customer ID, resource ID) to a cell ID before routing. The tension is that this lookup sits on the critical path of every request, so its availability requirement is stricter than any single cell’s; if the mapper is down, the whole fleet is unreachable, which would defeat the isolation the cells provide. The standard resolution is to make the mapping a read-mostly, cache-friendly store — a DynamoDB Global Table, Spanner, etcd, or even a periodically-shipped static config file — and to cache it aggressively at the routers with a TTL of minutes, which is acceptable precisely because mappings change rarely. Updates happen only on deliberate operational events: tenant onboarding, cell rebalancing, and tenant migrations. The consistency model is intentionally weak — the mapping need only be eventually consistent across routers, since a brief window where two routers disagree during an update is tolerable. The most important property is the failure mode: a router that cannot reach the mapping service must serve from its local cache rather than failing closed, so that a mapper outage degrades to “no new mapping changes propagate” rather than “no requests route.” This is why many designs eliminate the synchronous lookup entirely by baking the cell ID into the session token: a JWT issued at login can carry a cell claim, and the router reads the claim instead of consulting the mapper.

Cell-Local State and Cross-Cell Async

Each cell holds the full vertical of services and data its tenants need, and the load-bearing rule is that no synchronous request path crosses a cell boundary. Concretely, cell N’s PostgreSQL holds only cell N’s tenant data, cell N’s Redis serves only cell N and never answers for cell M, and cell N’s dashboards, logs, and traces are scoped to cell N. The hard part is the legitimate product feature that genuinely needs data spanning cells — search across all tenants, organization-wide reporting, global leaderboards. The disciplined answer is to forbid synchronous cross-cell calls and route those needs through an asynchronous layer instead: each cell emits per-cell events to a stream (Kafka, Amazon EventBridge, Kinesis), and a separate global aggregation pipeline consumes those events to build the cross-cell view. From the cells’ perspective this pipeline is read-only and decoupled — it can lag or fail entirely without affecting the cells’ ability to serve their own traffic. The moment a feature is implemented as “cell 1 synchronously calls cell 2,” cellular isolation has silently been lost (see the boundary-leakage pitfall above).

The Shared Layer Discipline

The minimal shared layer — identity, billing, cell mapping, cross-cell aggregation — is the chief residual risk in a cellular system, because by definition its failure can touch all cells at once, reintroducing the very fleet-wide blast radius cells exist to eliminate. The discipline is to architect each shared service so its outage is survivable by the cells. Identity/single-sign-on must keep authenticated existing sessions working even when the identity service itself is unreachable, which is why long-lived signed tokens (JWTs the cells can validate locally without a callback) are preferred over per-request identity lookups. Billing is made asynchronous and batched — usage events flow from cells to billing on a delay, so the billing service can be down for hours without touching the request path. The cell-mapping service is cached at the routers, so a brief mapper outage does not affect already-routed or cached requests. Cross-cell aggregation is explicitly async, so its pipeline can lag arbitrarily without user-visible effect. The mental rule AWS and practitioners converge on is to treat every shared service as if its outage budget were zero and engineer the cells to keep serving when it is gone.

Operational Considerations

Per-Cell Deployment Pipelines

The deployment story is where cellular pays off most visibly and where its operational tax is most felt. Each cell deploys independently, with CI/CD pipelines parameterized by cell ID, and the standard rollout is a wave deployment: deploy to cell 1, wait and monitor for a defined soak period, then cell 2, and so on. A regression that escaped pre-production is therefore caught after a single cell’s tenants experience it, bounding the damage to one cell’s worth of customers rather than the whole fleet. Pre-production and canary cells absorb the riskiest changes first, and because each cell is an independent deployment target, rollback can be surgical — reverting only the affected cell limits collateral damage and avoids the all-or-nothing rollback of a monolith. The cost is rollout latency: a soak-per-cell discipline turns a five-minute fleet-wide push into a multi-hour staged rollout, which is the deliberate trade of speed for safety discussed in the pitfalls.

Per-Cell Observability

Observability has to work at two granularities simultaneously, and getting this wrong is one of the most common ways a cellular migration disappoints. On-call engineers need aggregated dashboards that roll system-wide health up across all cells (to answer “what is the overall error rate?”) and per-cell drill-downs for cell-specific incidents (to answer “which cell is on fire?”). The tenant-to-cell mapping must itself be available to on-call engineers, because the first question when a tenant complains is “which cell is this customer on?” — trivial in a monolith, a lookup in a cellular system. Alerting must be cell-aware: an error spike confined to one cell should page that cell’s owner, not trigger a fleet-wide pager fan-out that masks which cell is actually affected. Without this tooling investment, the per-cell fragmentation that buys blast-radius isolation also fragments the operator’s view during exactly the incidents where a clear view matters most.

Per-Cell Capacity Planning

Capacity planning is where cellular’s raw-resource cost surfaces. Each cell must be sized for its assigned tenants’ peak load plus headroom — and the headroom must often include enough spare to absorb some of a failed peer cell’s traffic (the “N−1 capacity” idea: provision so the survivors can carry on if one cell is lost). Because that headroom is replicated per cell rather than pooled across the whole fleet, total provisioned capacity is roughly N × (per-cell peak + per-cell headroom), which is strictly more than a single shared pool that amortizes headroom across all customers. Sizing is not set-and-forget: as tenants grow or shrink, a cell that was comfortably provisioned drifts toward either overload or waste, so cell sizing and tenant placement must be revisited periodically as a deliberate operational activity (see the rebalancing pitfall).

Cellular Anti-Patterns

The “Logical Cell” Trap

A team partitions its API into “cell 1, cell 2, cell 3” but all share the same database. This is not cellular — it’s just a sharded API in front of a shared store. The blast radius of the database is still global; cellular benefits don’t materialize.

  • True cellular requires per-cell stateful services.
  • Per-cell databases are a hard requirement; shortcuts here are not cellular.

The “Just-Add-a-Router” Trap

A team adds a routing layer in front of an existing monolithic system, declares it “cellular,” but the underlying system is unchanged. The router is just dispatch logic; the shared monolith behind it has the same blast radius as before.

  • Cellular requires the system behind the router to be partitioned.
  • Routing is necessary but not sufficient.

The “Slowly Drifting Cells” Trap

Initially, all cells run the same code. Over months, slight divergences accumulate (cell 3 has a feature flag enabled that cell 1 doesn’t; cell 2 is on a slightly older release because its deploy was paused for a customer-specific issue). Eventually, cells run subtly different code, making cross-cell debugging extremely hard.

  • Discipline: configuration must be explicitly per-cell or universally consistent.
  • Periodic audits of cell-by-cell configuration drift.
  • Tooling that surfaces inter-cell version differences.

Glossary of Terms

  • Cell: an independent, self-contained replica of the system serving a subset of tenants/users.
  • Stamp: Microsoft Azure terminology for the same concept.
  • Pod: Salesforce terminology (predates Kubernetes Pods); essentially a cell.
  • Blast radius: the scope of customers/data affected by a single failure.
  • Shuffle-sharding: assigning each tenant a subset of cells rather than a single cell, with combinatorial blast-radius bounds.
  • Cell mapping: the registry that translates tenant ID to cell ID.
  • Wave deployment: rolling out changes cell-by-cell over time.
  • N-1 capacity: provisioning enough capacity that the loss of one cell can be absorbed by the survivors.

Future Directions and Open Problems

Where the Field is Heading

  • More AWS services published with cellular guidance: the 2023 AWS whitepaper marks an inflection point where AWS is publicly recommending cellular structure as a standard pattern, not an internal-only secret.
  • Cellular tooling and frameworks: there is no equivalent of “Kubernetes for cells” yet — most cellular implementations are bespoke. Frameworks that automate cell provisioning, deployment waves, and cross-cell async could lower the adoption barrier.
  • Adoption by mid-size companies: historically cellular was for hyperscale (AWS, Salesforce). Slack’s 2023 migration shows mid-size companies adopting it; the pattern is becoming mainstream.
  • Composition with serverless: a single cell can be entirely serverless (Lambdas, DynamoDB, S3 within a cell boundary). The economics shift the cell-size calculation.

Open Research and Operational Questions

  • Optimal cell size: there is no universal answer, and AWS explicitly declines to give a fixed percentage — its Cell sizing guidance says the maximum cell size “will vary per-service” and is bounded below by economy-of-scale and above by testability and account/service quotas, with a known per-cell capacity ceiling (transactions/second, tenants, or GB/second) as the real sizing input. The right size depends on operational maturity and failure-tolerance requirements.
  • Cross-cell consistency: when product features genuinely need cross-cell data (organization-wide search, billing aggregation), what is the right consistency model? Eventual consistency is the dominant answer; strong cross-cell consistency is rare.
  • Migration-without-downtime: moving a tenant from cell A to cell B without disruption is a non-trivial distributed-systems problem. Tooling is bespoke per company.

Cost and Maturity: an Honest Accounting

Two questions recur and resist a clean answer. The first is how much operational maturity cellular really demands. The published evidence is consistent in one direction: large migrations are multi-year (Slack’s critical-services migration took about 1.5 years; AWS evolved its services over far longer), and they surface dozens of buried single-instance assumptions. But cellular does not strictly require enormous infrastructure — AWS is explicit that “building a cell-based architecture doesn’t necessarily mean having to double, triple, or more your application’s infrastructure … It might be that your application has 30 hosts, and in a cell-based architecture it has the same 30 hosts, but with a cell router and with tasks that are distributed or grouped between cells.” So the dominant cost is operational and engineering (per-cell pipelines, aggregated observability, cross-cell async refactors), not necessarily raw hardware.

The second is whether cellular is cheaper than non-cellular at a given scale, and this is genuinely contested. Cellular raises some costs (per-cell capacity headroom does not amortize across the whole fleet the way a single shared pool does; N deployment targets multiply tooling and operations) while lowering others (the expected cost of incidents — customer-incident-hours, SLA credits, reputational damage — drops with blast radius). Whether the net is positive depends entirely on a workload’s incident profile: a system whose incident cost is dominated by rare-but-total outages benefits enormously; a system with frequent, naturally-contained failures may not recoup the operational tax. There is no universal break-even.

Uncertain

Verify: the claim that cellular is net-cheaper (or net-costlier) at a given scale. Reason: this is a workload-specific economic trade-off with no published general result; it depends on the relative size of capacity-headroom and operational-tooling costs versus avoided incident costs, none of which generalize across companies. To resolve: it does not resolve to a single answer — the honest position is “it depends on the incident-cost profile,” as stated above.

Common Interview Discussion Points

  • “What is cell-based architecture and why use it?” Replicate the entire stack (services, data, deployment) into independent cells, route each tenant to its assigned cell. Provides blast-radius isolation: a failure or bad deploy affects only one cell, not the whole customer base. Cite AWS Builders’ Library and the 2023 cellular architecture whitepaper.
  • “How is this different from sharding?” Sharding partitions data; cells partition the entire vertical stack including application servers. An application bug brings down all customers in a sharded system; a cellular system isolates the bug to one cell.
  • “How do you decide cell size?” Trade-off: smaller cells = finer blast radius but more operational overhead; larger cells = coarser but more manageable. AWS deliberately gives no fixed percentage — size each cell by a concrete per-cell capacity ceiling (transactions/second, tenant count, GB/second), bounded below by economy-of-scale and above by full-scale testability and account/service quotas. The “10 cells = 10% each, 100 = 1% each” figures are an illustration of how blast radius shrinks with count, not a sizing recommendation. Adjust based on operational maturity and worst-case-acceptable customer impact.
  • “How do you handle a hot tenant?” Move them to a dedicated cell, or use shuffle-sharding to spread their load across multiple cells. Cite AWS’s Route 53 shuffle-sharding pattern.
  • “What goes in the shared layer?” Identity, billing, cell-mapping, sometimes async cross-cell aggregation. Keep it minimal; design with paranoia because outages cascade across all cells.
  • “How do you migrate from monolithic to cellular?” Build the router and mapping first, refactor for one second cell, migrate canary tenants, scale up cell count over months. Slack and Salesforce both took multiple years.
  • “What’s shuffle-sharding?” Each tenant uses K cells out of N, distributing load across the subset. Mathematically bounds the chance that another tenant’s K-set fully overlaps with a misbehaving tenant’s K-set. Cite the Brooker 2020 post.
  • “How do cells interact with multi-region?” Compose: cells can be regional (one cell per region) or sub-regional (multiple cells per region). Both axes provide different forms of blast-radius and fault-domain isolation.
  • “What’s the operational cost?” N times the dashboards, deployment pipelines, and runbooks. Significant tooling investment required. Operations team typically needs to grow 50–80 % to operate cellular at the same maturity as monolithic.
  • “What goes wrong with cellular?” Hot cells, cell-boundary leakage as features evolve, the shared layer becoming a new monolith, expensive cross-cell migration, capacity-headroom multiplication, debugging cross-cell issues.
  • “Can a small startup use cellular?” Generally no — the operational cost dwarfs the benefit at small scale. Defer until the team has experienced the all-customer-outage failure mode and feels its pain.

See Also