---
type: Axis
title: distribution (topology axis)
description: The distribution/topology architecture axis — how the system is spread across processes and hosts (single-process → multi-host → geo). A system-singleton axis whose commitment surface is the interface/wire contract; worked example is the in-process → per-project daemon move.
tags: [axis, architecture, distribution, topology, daemon, rfc-75, deep]
timestamp: 2026-06-18T00:00:00Z
---

# Distribution (topology axis)

> **DEEP axis (5A.2).** Full §6 depth with a worked example from the skill's own
> history — the in-process MCP → per-project daemon topology climb (3.5.0).

## Concept

Distribution is the **topology** axis (RFC #75 §3): how the system's work is
spread across processes and hosts. The ladder runs single-process (everything in
one address space) → multi-process/host (a service split across processes,
possibly hosts, talking over a wire) → geo-distributed (spread across regions,
latency + partition are first-class). Its **commitment surface is the
interface/wire contract** (§4) plus the topology: the moment work crosses a
process boundary, the call becomes a wire contract that must be versioned and
that can fail partially. Its **scope is system-singleton** (§5): a topology is
chosen once for the system.

## Why it is an axis (discriminator test — §2)

1. **Ordered tiers** — each rung spreads the system further (more boundaries).
2. **Cross-cutting bundle** — a rung dictates IPC/RPC mechanics, serialization,
   the failure model (partial failure, retries), liveness/health, and the tests.
3. **Asymmetric migration cost** — splitting an in-process call into a wire call
   means designing a contract, serialization, failure handling, and liveness —
   you cannot collapse it back cheaply once consumers depend on the boundary.
4. **Requirement-keyed selection** — falsifiable probes pick the rung.

## Schema view (the §6 entry — validated by `axis_catalog`)

```yaml
id: distribution
kind: architecture-axis
scope: system-singleton
selection:
  probes:
    - "Does everything run in one address space with in-memory calls? → single-process."
    - "Must work outlive a single client invocation / be shared by concurrent clients? → multi-process (a daemon)."
    - "Do components run on different hosts and talk over a network? → multi-host."
    - "Must the system span regions with partition + latency as first-class concerns? → geo."
    - "Has an in-process call become a boundary crossing? → it is now a wire contract: version it + handle partial failure + add liveness."
composes_with:
  - "CAP positioning = consistency × distribution"
applies_when: []
tiers:
  - tier: single-process
    commitment_delta:
      surface: interface-wire-contract
      delta: "all components share one address space; calls are in-memory function calls. No serialization, no partial-failure, no liveness story needed."
    admin_tool: "none — start/stop the one process."
    enforcement:
      - "no hidden process boundary; a call either returns or the whole process is down."
    tests:
      - "the happy path + in-process error propagation."
    forecloses: "sharing live state across invocations or clients."
    migration_cost_to_next: "high — extract a service boundary: wire contract + serialization + failure model + liveness."
  - tier: multi-process
    commitment_delta:
      surface: interface-wire-contract
      delta: "a long-lived service (daemon) reached over a local wire (HTTP/socket); concurrent clients share its state. Calls can fail partially; the service has a lifecycle."
    admin_tool: "spawn/shutdown/health endpoints; restart + drain machinery."
    enforcement:
      - "every client call is a versioned wire request with a defined failure mode + retry."
      - "the service publishes liveness (health + heartbeat) distinct from request success."
    tests:
      - "a client survives a service restart; a transient wire error retries; spawn-once-under-race holds."
    forecloses: "in-memory call simplicity; the boundary is now load-bearing."
    migration_cost_to_next: "medium — run the service on a separate host (network, discovery)."
  - tier: multi-host
    commitment_delta:
      surface: interface-wire-contract
      delta: "components run on different hosts over a real network; discovery, network partition, and host loss are explicit."
    admin_tool: "service discovery + per-host health dashboard; deploy orchestration."
    enforcement:
      - "calls handle network partition + timeout; no shared local FS assumption."
    tests:
      - "a host loss degrades gracefully; partition does not corrupt shared state."
    forecloses: "single-host assumptions (shared FS, localhost)."
    migration_cost_to_next: "high — span regions: latency + partition tolerance everywhere."
  - tier: geo
    commitment_delta:
      surface: interface-wire-contract
      delta: "the system spans regions; cross-region latency + partition are first-class. Reads/writes are region-aware."
    admin_tool: "region routing + cross-region replication console."
    enforcement:
      - "every cross-region path tolerates partition + bounds latency; writes pick a consistency model."
    tests:
      - "a region partition keeps each region serving; cross-region convergence is verified."
    forecloses: "global-synchronous reasoning; everything is latency/partition-aware."
    migration_cost_to_next: "n/a — top of the ladder."
examples:
  - "The skill's own climb: the recording/composition logic moved from in-process MCP calls to a per-project daemon (3.5.0) — once work had to outlive a single MCP invocation and serve the live UI, it became a long-lived service reached over a local HTTP wire. That promoted the call to a wire contract with a real lifecycle: POST /shutdown + spawn_died restart (4.2.0a8), fixed-port TIME_WAIT rebind (#743/4.2.0a11), and the spawn-race split-brain flock fix (#769). Sits at multi-process; not multi-host (per-project, single-machine by design)."
```

## Selection procedure (§8)

Bidirectional check; chosen once for the system. Recorded in the system
architecture record; a new cross-process boundary that lacks a versioned
contract + failure model is a systems-analysis D-finding.

## Composition (§5)

Distribution × consistency = **CAP positioning** — once writes cross a partition
boundary you trade consistency for availability. Rule authored in 5A.3.
