# A concern is a component

> This section covers how work is partitioned into concerns and how many parties it needs.

Page: Architecture · Scale
Canonical: https://banes-lab.com/software-architecture/scale#a-concern-is-a-component

This section is stop 97 of 102 in the learning route. Previous: [47 - The honest gaps](https://banes-lab.com/disciplined-methodology/ship/the-honest-gaps.md). Next: [02 - The ceiling moves by cost](https://banes-lab.com/software-architecture/scale/the-ceiling-moves-by-cost.md). It builds on [01 - A system is a graph](https://banes-lab.com/software-architecture/model/a-system-is-a-graph.md), [44 - Scale follows from structure](https://banes-lab.com/disciplined-methodology/ship/scale-follows-from-structure.md).

This section covers how work is partitioned into concerns and how many parties it needs. The partition is derived rather than drawn, as shown in [A1·a floor and ceiling](https://banes-lab.com/software-architecture/scale#a-concern-is-a-component-panel-a), one body of work is walked in [A1·b three components](https://banes-lab.com/software-architecture/scale#a-concern-is-a-component-panel-b), and the records the derivation reads are typed in [A1·c the derivation's records](https://banes-lab.com/software-architecture/scale#a-concern-is-a-component-panel-c). The practice for a body of work is described in [scale follows from structure](https://banes-lab.com/disciplined-methodology/ship/scale-follows-from-structure.md) on the methodology page.

### Partition, floor, ceiling

Concerns are drawn as areas of a work list, so a seat owns a region rather than a component, and every coupled edit crosses two seats. Two seats each own half of one coupled pair of surfaces, every change one makes forces a change in the other's, and the surface between them fills with items about the same edit from both sides. A concern drawn as an area of a task list follows how the list was written, and a list is written by one developer on one day, so its areas cut across the couplings that actually force changes.

For this reason a concern is a connected component of the relation that joins two surfaces when a change to one forces a change to the other. The work is cut along what forces what rather than along what the work list happened to group. In practice, the surfaces a body of work touches are enumerated, and the pairs that force each other are recorded with evidence, where a change to one cannot land without a change to the other. The connected components of that relation are the concerns, each gets one owner, and the number of components is the floor. The fan-in on each [shared surface](https://banes-lab.com/pag/orchestration/shared-surfaces.md) is measured from the claims already recorded against it, and the worst fan-in sets the ceiling. A count is chosen inside that range, and the partition is written down beside the choice.

To check this, take any two concerns and find one change that forces edits in both. If one exists, the partition put a forcing edge across a boundary, and the two concerns are one component. The relation is chosen once, and that choice is the one place judgement enters. Two defensible readings of what forces what yield component counts far apart, so the claim is a derivation with a choice at the bottom. The choice is answerable to evidence, and where no mechanism yet computes the partition or the fan-in, that absence is written down as debt with its operands rather than left to read as a measurement.

### A concern is a bounded context for people

A concern is a [bounded context](https://banes-lab.com/records/arch/bounded-context.md) drawn for people rather than for models, and [context mapping](https://banes-lab.com/records/arch/context-mapping.md) is the activity that draws it. A concern is a component of the forcing relation for the same reason a bounded context is a region of one model, because inside it one party can be authoritative, and across its edge two parties have to be able to disagree. [Separation of concerns](https://banes-lab.com/records/arch/separation-of-concerns.md) at the scale of seats is the same principle as at the scale of files, and it is derived the same way, from what forces what.

Volume is the wrong operand for the floor. Quantity divides across parties and argues for a longer schedule, never a wider one. What forces a second party is indivisibility, a concern that has to be able to contradict another while both stay authoritative, and the floor counts those. [Partitioning](https://banes-lab.com/records/arch/partitioning.md) by volume is [horizontal scaling](https://banes-lab.com/records/arch/horizontal-scaling.md) of people, and it buys [throughput](https://banes-lab.com/records/arch/throughput.md) where the concerns are already separate and nothing where they are not.

### Fan-in, measured

The ceiling is set by fan-in rather than by the count, because a surface with one writer cannot have its volatility raised by adding a party, and staleness rises only where parties converge on one subject. Ownership bounds fan-in without defining it, since a formally owned surface that many parties reason about behaves like [shared mutable state](https://banes-lab.com/records/arch/shared-mutable-state.md), and the concentration is continuous.

For this reason the ceiling is measured and never declared. A count chosen because it felt right is a bound nothing can disagree with, and so it bounds nothing. Fan-in read from the claims already recorded against each surface is a number a second reader can recompute, and the ceiling follows from the worst of them.

A1·a floor and ceiling

```mermaid
flowchart TB
surfaces["The surfaces a body of work touches"]
relation["Join two surfaces when a change to one forces a change to the other"]
components["The connected components · one per concern"]
floor["Floor · the number of components"]
fanin["Fan-in · how many parties' claims rest on one surface, measured from traffic"]
ceiling["Ceiling · where claims on one surface stop surviving composition"]
count["A count inside the range · with the partition written down"]
surfaces --> relation --> components --> floor --> count
surfaces --> fanin --> ceiling --> count
choice["The one choice · which reading of forces"]
choice -. answerable to evidence, never taste .-> relation
```

A1·b three components

```mermaid
flowchart LR
subgraph one["concern · one seat"]
schema["schema"] --- loader["loader"]
loader --- validator["validator"]
end
subgraph two["concern · one seat"]
view["view"] --- renderer["renderer"]
renderer --- styles["styles"]
end
subgraph three["concern · one seat"]
pipeline["pipeline"] --- reporter["reporter"]
end
shared["shared surface · fan-in from every seat"]
validator -.-> shared
renderer -.-> shared
reporter -.-> shared
```

A1·c the derivation's records

```typescript
export interface Forces {
readonly from: SurfaceId;
readonly to: SurfaceId;
readonly evidence: string;
}

export interface Concern {
readonly id: ConcernId;
readonly surfaces: readonly SurfaceId[];
readonly owner: SeatId | null;
}

export interface Claim {
readonly author: SeatId;
readonly cites: readonly SurfaceId[];
readonly observedAt: Ordinal;
}

export interface Bounds {
readonly floor: number;
readonly ceiling: number;
readonly partition: readonly Concern[];
readonly derivedBy: "mechanism" | "declared-unbuilt";
}
```

## Links to

- [Scale follows from structure](https://banes-lab.com/disciplined-methodology/ship/scale-follows-from-structure.md)
- [Shared surfaces](https://banes-lab.com/pag/orchestration/shared-surfaces.md)
- [Bounded Context](https://banes-lab.com/records/arch/bounded-context.md)
- [Context Mapping](https://banes-lab.com/records/arch/context-mapping.md)
- [Separation of Concerns](https://banes-lab.com/records/arch/separation-of-concerns.md)
- [Partitioning](https://banes-lab.com/records/arch/partitioning.md)
- [Horizontal Scaling](https://banes-lab.com/records/arch/horizontal-scaling.md)
- [Throughput](https://banes-lab.com/records/arch/throughput.md)
- [Shared Mutable State](https://banes-lab.com/records/arch/shared-mutable-state.md)

## Linked from

- [Composing a collaboration](https://banes-lab.com/pag/orchestration/composing-a-workflow.md)
- [Scale follows from structure](https://banes-lab.com/disciplined-methodology/ship/scale-follows-from-structure.md)
