Skip to content
Separation of Concerns Between Theseus and Cells

Separation of Concerns Between Theseus and Cells

Theseus and Cells solve different problems and must not blur into each other. Theseus is the developer platform: how a modular feature is built, packaged, instrumented, shipped — and, for Self-Managed customers, installed and operated. Cells is the infrastructure architecture: where and how GitLab.com runs those features at scale, in isolated blast-radius boundaries. On GitLab.com, Cells is Tenant Scale’s work; Dedicated environments are operated by the Dedicated team. Both are fleet operators: they orchestrate the artifacts Theseus produces, and that orchestration sits outside Theseus. This page sets out the responsibilities on each side of that line and the contract that connects them.

The short version: Theseus produces a self-describing, deployable artifact; Cells decides where that artifact runs and feeds it the values for each place. Everything else on this page is a consequence of that split.

What Theseus owns

Theseus owns everything about a service that is true regardless of where the service runs — and, for Self-Managed customers, the automation that installs and operates it:

  • The service shape. Scaffolding via common-template-copier, the three-layer architecture, and the conventions the go-service-template demonstrates as working code.
  • The library layer. LabKit v2: structured logging, metrics, tracing, validated configuration, secrets, and feature flags — the same instrumentation from laptop to production.
  • Packaging and artifact generation. A Fairway manifest in, a production-grade Helm chart out, built and released through common-ci-tasks pipelines. The chart is Theseus’s finished product.
  • The runtime contract. CONFIG_DIR for configuration, mounted infrastructure wiring, health endpoints — identical across every deployment target, so a service never branches on its environment.
  • The paved-path opinions. The strategy pages on this site — such as feature flags and co-located dashboards — are Theseus deciding how modular features behave, wherever they land.
  • Self-Managed installation and day-2 operations. The GitLab Operator, Crete, and OAK install and operate the same artifacts on customer infrastructure.

None of this requires knowing how many cells exist, which tenants live where, or when a rollout advances. If a Theseus component needs that knowledge, the boundary has been drawn in the wrong place.

What Cells owns

Cells owns everything about where services run and which values they run with:

  • Cell provisioning and lifecycle. The cell is the primary isolation boundary for all modular services — tightly coupled within, asynchronous across (see Cellular architecture and Platform bindings).
  • The tenant model. The single source of truth for what runs in which cell, with which configuration. Theseus consumes what it materialises; it never defines it.
  • Fleet orchestration. Ring-based rollouts and cell-by-cell promotion, driven through AMP, Instrumentor, and Argo — the machinery that takes a released chart and walks it across the fleet. This machinery is operated by the fleet-owning teams: Tenant Scale on GitLab.com, the Dedicated team for Dedicated.
  • Routing and discovery. A request finding its cell is a Cells problem; no service participates in solving it.
  • Per-cell configuration delivery. Materialising each cell’s values from the tenant model and installing the chart with them (see appConfig on Cells).

The boundary between them

The contract at the boundary is the platform bindings model, which is itself the core contract applied to deployment: services declare what they need, and each binding decides how the declaration is satisfied in its environment. Cells is one binding among several — the Cells and Dedicated binding, a COM module for Instrumentor — not a special case that services code against.

The hand-off artifact is the Fairway-generated Helm chart. Theseus produces it; the Cells binding installs it with per-cell values. Inside the pod the contract is identical to every other environment — the same ConfigMap, the same mount, the same CONFIG_DIR:

    flowchart LR
    subgraph theseus ["Theseus (developer platform)"]
        svc["Service repo<br/>code + fairway.yaml"]
        ci["common-ci-tasks<br/>build & release"]
        chart["Fairway-generated<br/>Helm chart"]
        svc --> ci --> chart
    end
    subgraph cells ["Cells (infrastructure architecture)"]
        tm["Tenant model"] --> inst["AMP / Instrumentor<br/>+ COM module"]
        inst --> values["Per-cell values"]
        values --> argo["Argo releases"]
        subgraph cell ["Cell N"]
            pod["Pod<br/>CONFIG_DIR contract"]
        end
        argo --> pod
    end
    chart --> argo
  

Two rules keep the boundary honest:

  • A modular feature must never know which cell it is in. Cell-awareness in application code couples the service to the topology and is a boundary violation. Anything that genuinely varies per cell arrives as configuration, delivered by the binding — the service reads values, not topology.
  • Design for absence. The same posture the feature flag strategy takes: a service behaves correctly whatever infrastructure surrounds it, because the binding — not the application — is responsible for what is present in an environment.

A service built against the runtime contract today needs no changes to run on Cells: only the source of its values differs.

What Theseus deliberately does not do

Anti-responsibilities matter as much as responsibilities — they are what stop the two efforts dissolving into one another:

  • No cell topology decisions. Theseus never decides how many cells exist, which tenants land where, or when a ring advances.
  • No fleet orchestration. Rollout ordering and cell-by-cell promotion — and rollout policy generally: rings, progressive and A/B rollouts, maintenance windows, and which customers upgrade when — belong to the fleet operators: Tenant Scale on GitLab.com, the Dedicated team on Dedicated. A service’s pipeline ends at a released chart; it does not reach into the fleet.
  • No tenant model ownership. Theseus consumes materialised values. It does not define, store, or serve tenant data.

The line cuts both ways:

  • Cells does not dictate service internals. Languages, frameworks, repository layout, and the shape of a service stay on the Theseus side. A cell installs charts; it does not review architecture.
  • Cells does not fork the contract. The Cells binding satisfies the same Fairway declarations every other binding satisfies. A “Cells-only” manifest field that services must set would be the boundary failing.

Open questions

The boundary is drawn; some assignments along it are still being settled:

  • Per-cell feature-flags instances. An instance of the feature-flags service per cell is the target — but is running it a Theseus component concern or Cells infrastructure?
  • Observability stack conventions. Strategies like co-located dashboards assume each cell runs a Grafana with the discovery sidecar. Who owns that guarantee?
  • Binding readiness vs tenant-model stability. How much of the Cells and Dedicated platform binding can be built and validated before the tenant-model integration stabilises?

Related reading

Last updated on