One Cluster or Many? This Isn't Actually a Close Call
It's tempting to imagine a single Kubernetes cluster spanning multiple regions, since it sounds simpler than coordinating several independent ones. In practice this is almost never the right architecture: the Kubernetes control plane assumes fast, reliable connectivity between its components, and stretching that across regions turns the control plane itself into a cross-region dependency — exactly the single point of failure that multi-region architecture exists to eliminate. The standard, well-tested pattern is independent clusters per region, each with its own fully self-contained control plane, coordinated at the application and infrastructure layer above Kubernetes rather than within it.
Cell-Based Architecture: The Pattern That Makes This Manageable
A cell is a fully self-contained, independently deployable unit that handles a complete slice of traffic or customers end to end, with no cross-cell dependency required for a normal request to succeed. Structuring a multi-region system as a set of cells — commonly one or more cells per region — gives active-active architecture a crucial property: a bad deployment, a resource exhaustion issue, or even a partial regional problem that affects one cell doesn't cascade into other cells, because they share no runtime dependency by design.
This maps naturally onto multi-region EKS: each regional cluster can host one or more cells, cell boundaries typically align with data partitioning boundaries (a given cell owns a specific shard of customers or data), and the blast radius of any single failure is bounded to whatever fraction of total traffic that one cell represents — a meaningfully different risk profile than a single region-wide cluster where a bad deployment can affect all traffic in that region simultaneously.
Cross-Cluster Service Discovery
Services within one regional cluster reach each other through standard Kubernetes service discovery. Services that occasionally need to reach a service in a different region — an intentionally rare pattern in a well-designed cell-based system, but sometimes unavoidable for shared, genuinely global resources — need a cross-cluster mechanism. Two common approaches: a service mesh with multi-cluster support, which extends the mesh's service registry and mutual TLS across cluster boundaries so a service can call another region's service using the same abstractions as a local call; or an explicit API gateway layer between regions, treating cross-region calls as external API calls with their own authentication, rate limiting, and observability, which is more operationally visible at the cost of more integration work per cross-region dependency.
The most reliable way to avoid cross-region service-mesh complexity is architectural: design cells and data partitioning so that the vast majority of requests never need to leave their originating region at all. Relying on engineering discipline to avoid unnecessary cross-region calls tends to erode over time as new features get added under deadline pressure; a data and cell boundary that structurally prevents the call from being needed in the first place holds up far better.
Keeping Regional Clusters Consistent: GitOps
Independent clusters create a real risk: configuration drift, where one region's cluster state quietly diverges from another's — a Helm chart version bumped in one region and forgotten in the other, a resource limit tuned manually during an incident and never backported. GitOps addresses this directly: a git repository holds the declarative desired state for every regional cluster, and an in-cluster controller continuously reconciles actual state to match it, flagging or auto-correcting drift rather than letting it accumulate silently. This also gives every configuration change — including emergency changes made during an incident — a reviewable, auditable history, which matters as much for governance as for consistency.
A practical structure: a shared base configuration (common Deployments, Services, resource policies) that every region inherits, layered with region-specific overrides (region-specific ingress hostnames, replica counts tuned to regional traffic) kept explicit and minimal, so the common case stays consistent by default and per-region divergence is a deliberate, visible choice rather than an accident.
Autoscaling Across Regions
Each regional cluster scales independently based on its own local traffic — there's no meaningful concept of a shared autoscaler spanning regions, since scaling decisions need to react to local load in near real time. What does need cross-region coordination is capacity planning for failover: each region's cluster needs enough headroom, whether through cluster autoscaling or pre-provisioned capacity, to absorb a meaningful share of another region's traffic if that region fails — the cascading-overload failure mode from Article 2's failure-modes discussion, translated into a Kubernetes capacity-planning requirement. Autoscalers tuned only for each region's normal steady-state load, without headroom for absorbing failover traffic, quietly undermine the whole active-active design.
Deployment Strategy Across Regions
Rolling out a change to all regions simultaneously reintroduces a single point of failure at the deployment level — a bad release can now take down every region at once instead of being contained to one. A staged rollout — deploying to one region first, verifying health and key metrics, then proceeding to the next — preserves the isolation benefit that active-active is supposed to provide, at the cost of a longer total rollout window. This deliberately trades deployment speed for blast-radius containment, which is almost always the right trade for a system where regional independence is the whole point.
Frequently Asked Questions
Should a multi-region system use one large EKS cluster or separate clusters per region?
Separate clusters per region, in almost every real-world case. A single cluster spanning regions makes the control plane itself a cross-region dependency and a shared failure domain, which defeats much of the purpose of going multi-region in the first place. Independent per-region clusters, coordinated at a layer above Kubernetes, keep each region's control plane genuinely independent.
What is cell-based architecture and how does it relate to multi-region?
Cell-based architecture partitions a system into fully independent, self-contained units (cells) that each handle a subset of traffic or customers end to end, with no cross-cell dependencies for a normal request. It's a natural fit for multi-region: each region can be structured as one or more cells, so a single cell's failure — whether from a bad deployment or a regional issue — can't cascade into other cells.
How do you prevent configuration drift between regional clusters?
GitOps — where a git repository is the single source of truth for every cluster's desired state, and an in-cluster controller continuously reconciles actual state to match it — is the most reliable practical answer. It makes drift visible and automatically correctable rather than something discovered manually during an incident, and it gives every regional configuration change a reviewable, auditable trail.