• Home
  • Disclaimer
  • Contact
  • Archives
  • About
  • Subscribe
  • Support
  • Advertise

Kernel Talks

Unix, Linux, & Cloud!

  • How-to guides
    • Howto
    • Disk management
    • Configurations
    • Troubleshooting
  • OS
    • HPUX
    • Linux
  • Miscellaneous
    • Software & Tools
    • Cloud Services
    • System services
    • Virtualization
  • Certification Preparations
    • AWS Certified Solutions Architect – Associate
    • AWS Certified Solutions Architect – Professional
    • AWS Certified SysOps Administrator – Associate
    • AWS Certified Cloud Practitioner
    • Certified Kubernetes Administrator
    • Hashicorp Certified Terraform Associate
    • Oracle Cloud Infrastructure Foundations 2020 – Associate
  • Tips & Tricks
  • Linux commands
You are here: Home / Cloud Services

Cell-Based Architecture on AWS, Part 6: Shipping Cells with IaC and ArgoCD

By Shrikant Lavhate | Published: August 18, 2026 | Modified: August 18, 2026



By this point in the series you’ve picked a partition key, chosen EKS or ECS as the substrate, worked out the networking, built in shuffle sharding and bake time, and made peace with what it all costs. What’s left is the least glamorous problem and the one that actually determines whether any of the above survives contact with a real team: how do you provision and update dozens of near-identical cells without dozens of near-identical ways for them to drift apart.

Shipping cells!

Infrastructure as code: the stamp pattern

The core idea is simple to state and easy to get subtly wrong in practice: write one module that describes a cell, and apply it once per cell with different inputs. A hands-on Terraform walkthrough of this pattern frames it as a blueprint you stamp out repeatedly, alongside a separately-built router layer that isn’t part of any individual cell’s module at all.

A minimal shape for that module looks something like this:

module "cell" {
  source   = "./modules/cell"
  for_each = var.cells

  cell_id       = each.key
  account_id    = each.value.account_id
  region        = each.value.region
  az            = each.value.az
  tenant_range  = each.value.tenant_range
}

variable "cells" {
  type = map(object({
    account_id   = string
    region       = string
    az           = string
    tenant_range = string
  }))
}

The detail that matters more than the module code itself is state isolation. Each cell’s Terraform state needs to be genuinely separate — a distinct backend key per cell, not just a shared workspace inside one state file — so that a plan or apply against cell-07 can’t accidentally touch cell-03. A shared state file for “all cells” quietly reintroduces exactly the coupling the whole architecture exists to avoid, just at the tooling layer instead of the runtime layer.

CDK works the same way conceptually, even though the syntax differs. AWS’s own reference implementation structures this as three separate stacks — one for shared ECR repositories, one for the routing components, and one for the cell blueprint, which gets deployed repeatedly, once per cell. Terraform, CDK, or CloudFormation, the stamp pattern is the same idea wearing different clothes.

A cell registry as the single source of truth

Once you’re past a handful of cells, you want one place that lists every cell that exists — its account, region, AZ, tenant range, and lifecycle status (active, draining, newly provisioned). This can be as simple as a cells.yaml checked into the same repo as your Terraform, or as robust as a DynamoDB table if other systems need to query it at runtime. What matters isn’t the storage mechanism, it’s that this registry becomes the one input that drives both your infrastructure provisioning and your application deployment generator — because the moment those two read from different sources of truth, you’ve created a gap where they can disagree about how many cells exist.

Cell registry

Deploying applications with ArgoCD

On the application side, ArgoCD’s ApplicationSet controller is built for exactly this fan-out. A list or git-file generator, sourced from the same cell registry, produces one child Application per cell (or per cell-and-app combination), rather than hand-maintaining one YAML file per cell per application.

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: order-service-cells
  namespace: argocd
spec:
  generators:
    - git:
        repoURL: https://github.com/your-org/gitops-cells.git
        revision: main
        files:
          - path: "cells/*/registry.yaml"
  template:
    metadata:
      name: 'order-service-{{cell_id}}'
    spec:
      project: order-service
      destination:
        server: '{{cluster_endpoint}}'
        namespace: order-service
      source:
        repoURL: https://github.com/your-org/gitops-cells.git
        targetRevision: main
        path: 'apps/order-service/overlays/{{cell_id}}'

Platform-wide baseline components — an ingress controller, cert-manager, the monitoring agents every cell needs regardless of tenant — are a good fit for a separate App-of-Apps hierarchy, kept distinct from the per-cell, per-tenant applications so a change to the shared baseline doesn’t get tangled up with a single cell’s release train.

Sync waves are worth using deliberately here: router configuration and any cell-registration step should land before the cell’s own workloads sync, not after, or you risk a cell coming online with traffic already routed to it before its services exist. And each cell’s rollout should carry its own canary and bake time — tying back to the deployment discipline from earlier in this series — rather than one canary standing in for the whole fleet. A fleet-wide canary defeats the purpose of having cells in the first place; the point was that a bad release only ever touches one of them at a time.

The habit that actually keeps this from falling apart

None of this tooling prevents drift on its own. What prevents drift is treating the cell registry as a change that goes through the same pull request and review path as any other production change, and making sure both the Terraform plan and the ArgoCD ApplicationSet read from that same file. When someone adds cell-12 to the registry, that one commit should be the trigger for both the infrastructure to get stamped out and the applications to start deploying into it — not two separate manual steps that someone has to remember to keep in sync.

That’s really the throughline of this whole series. Cell-based architecture starts as a resiliency idea — smaller blast radius, contained failure — but by the time it’s running in production it’s mostly a delivery-engineering discipline. The isolation only holds up if your pipeline can safely stamp out cell N+1 in an afternoon, deploy into it with the same confidence as cell N, and tear it down just as cleanly if it turns out you didn’t need it. If your tooling can’t do that yet, the resilience story is still theoretical — and that’s a good place to start the next iteration of the design, rather than the last one.

⇠ Previous article
Cell-Based Architecture on AWS, Part 5: Well-Architected and the Real Cost of Cells

Related stuff:

  • Know about Amazon GuardDuty Investigation: AI-powered security analysis
  • Self-Managed S3 Buckets for Lambda Code: You Finally Own the Artifact
  • How to extend EBS & filesystem online on AWS server
  • AWS CloudFormation IaC Generator!
  • How to assign Elastic IP to EC2 Linux instance
  • Preparing for 1Z0-1085-20 Oracle Cloud Infrastructure Foundations 2020 Associate Exam
  • Journey to AWS Certified Solutions Architect – Professional Certification SAP-C01
  • How to transfer the domain to Route 53
  • Amazon ECS basics for beginners
  • Understanding the basics of Lambda Function URLs
  • Difference between elastic IP and public IP
  • Coding GitHub action for automated CloudFormation template linting

Filed Under: Cloud Services Tagged With: applicationset, argocd, cell-based-architecture, gitops, infrastructure-as-code, Terraform

If you like my tutorials and if they helped you in any way, then

  • Consider buying me a cup of coffee via paypal!
  • Subscribe to our newsletter here!
  • Like KernelTalks Facebook page.
  • Follow us on Twitter.
  • Add our RSS feed to your feed reader.

Share Your Comments & Feedback: Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Get fresh content from KernelTalks

  • Email
  • Facebook
  • RSS
  • Twitter

Get Linux & Unix stuff right into your mailbox. Subscribe now!

* indicates required

This work is licensed under a CC-BY-NC license · Privacy Policy
© Copyright 2016-2026 KernelTalks · All Rights Reserved.
The content is copyrighted to Shrikant Lavhate & can not be reproduced either online or offline without prior permission.