# Execution joins the halves

> This section covers execution, the layer where the two halves meet, as shown in [the core split].

Page: Architecture · Principles
Canonical: https://banes-lab.com/software-architecture/principles#execution-joins-the-halves

This section is stop 60 of 102 in the learning route. Previous: [04 - Computation and resource](https://banes-lab.com/software-architecture/principles/computation-and-resource.md). Next: [06 - The structural domain](https://banes-lab.com/software-architecture/principles/the-structural-domain.md). It builds on [04 - Computation and resource](https://banes-lab.com/software-architecture/principles/computation-and-resource.md).

This section covers [execution](https://banes-lab.com/records/layer/execution-core.md), the layer where the two halves meet, as shown in [E1·a the core split](https://banes-lab.com/software-architecture/principles#execution-joins-the-halves-panel-a). Execution has its own rules, each the refusal of one improvised join, and one exchange under those rules is shown in [E1·b one exchange](https://banes-lab.com/software-architecture/principles#execution-joins-the-halves-panel-b) and typed in [E1·c execution as types](https://banes-lab.com/software-architecture/principles#execution-joins-the-halves-panel-c).

### Events, growth, order, errors

Control flow is usually improvised per call site, so the same two halves are joined a different way in every place they meet. A child calls back into its parent, the parent is replaced, and the child keeps calling into something that no longer exists, while the error that would have said so was a string no consumer parsed. A callback couples a child to a parent it should not know, a retraction is a second path every reader must handle, a clock is a dependency on the host, and a sentence in an error is a contract no consumer can dispatch on.

For this reason execution joins the halves through events rather than callbacks, appends rather than retracts, and treats errors as part of the language. The system owns the sequence and the vocabulary rather than borrowing the host's clock and prose. In practice, a child announces what happened as an event and the parent decides what to do with it, so the child never holds a reference to what reacts. A correction is appended as a new record that supersedes rather than edits history, and an earlier state is restored by reinstantiating from a snapshot rather than by patching in place. Ordering uses a monotonic sequence the system owns, never the host's clock. Every error is a typed value in the system's own vocabulary, each error is marked as halting or carried, and a guard that fails does so closed.

To check this, follow one event from the child that emits it to every parent that reacts, and one error from where it is raised to where it is handled. A callback that runs upward, a retraction, or an error handled by string comparison is a place where execution has no rule. Execution rules govern how [computation and resources](https://banes-lab.com/software-architecture/principles/computation-and-resource.md) interact at runtime, and they do not decide what either half is. A resource that halts on a broken invariant is obeying the resource rule, and a computation that marks an uncertainty is obeying the computation rule. Execution only carries the result between them.

### Events and growth

[Event-driven architecture](https://banes-lab.com/records/arch/event-driven-architecture.md) is the shape the first rule produces. [Domain events](https://banes-lab.com/records/arch/domain-events.md) are what a child emits, the [publish/subscribe pattern](https://banes-lab.com/records/arch/publish-subscribe-pattern.md) is how a parent hears them without the child knowing who listens, and an [event bus](https://banes-lab.com/records/arch/event-bus.md) is the mechanism that carries them. The [observer pattern](https://banes-lab.com/records/arch/observer-pattern.md) is the same relation inside one process. Execution may counter-propose by emitting an intent a parent can refuse, which is [asynchronous communication](https://banes-lab.com/records/arch/asynchronous-communication.md) with the refusal kept explicit.

An [append-only log](https://banes-lab.com/records/arch/append-only-log.md) is the growth rule as a store, and [event sourcing](https://banes-lab.com/records/arch/event-sourcing.md) is it as a whole architecture, where the current state is a fold over the events and a correction is a new event that supersedes. Backtracking is by snapshot and reinstantiation rather than by patching state in place, which is the [memento pattern](https://banes-lab.com/records/arch/memento-pattern.md) held as a rule rather than a trick.

Ordering is by a monotonic sequence or an append-only id, never a wall clock. A clock is a dependency on the host and a sequence is a dependency on nothing, which is why [causality](https://banes-lab.com/records/arch/causality.md) is tracked with [Lamport clocks](https://banes-lab.com/records/arch/lamport-clocks.md), [vector clocks](https://banes-lab.com/records/arch/vector-clocks.md) or [hybrid logical clocks](https://banes-lab.com/records/arch/hybrid-logical-clocks.md) rather than timestamps, and why [event ordering](https://banes-lab.com/records/arch/event-ordering.md) is a constraint the system owns. A [happens-before relationship](https://banes-lab.com/records/arch/happens-before-relationship.md) is derivable from a sequence and never from two clocks.

### Errors as language

Errors are part of the language. [Error handling](https://banes-lab.com/records/arch/error-handling.md) uses the system's own vocabulary and the errors are machine-processable, so a consumer dispatches on an error rather than parsing a sentence. An [inconsistent error model](https://banes-lab.com/records/arch/inconsistent-error-model.md), one boundary raising and another returning a code, is the anti-pattern this rule refuses, and [exception control flow](https://banes-lab.com/records/arch/exception-control-flow.md) is its twin.

A resource invariant that breaks [fails fast](https://banes-lab.com/records/arch/fail-fast.md) and halts, because carrying on with a corrupt handle is worse than any crash. A computation that is uncertain marks the uncertainty and carries on, because temporary inconsistency in data is acceptable exactly while it is visible. [Defensive programming](https://banes-lab.com/records/arch/defensive-programming.md) is the wrong reflex here, and the practice that replaces it is described in [fail at the boundary](https://banes-lab.com/disciplined-methodology/build/fail-at-the-boundary.md) on the methodology page. [Fail safe](https://banes-lab.com/records/arch/fail-safe.md) and [fail secure](https://banes-lab.com/records/arch/fail-secure.md) are the same decision made once for a domain rather than per call site.

E1·a the core split

```mermaid
flowchart TB
subgraph computation["Computation · what happens to data"]
pure["pure functions · immutable · idempotent"]
marked["uncertainty marked, never hidden"]
end
subgraph resource["Resource · where data lives"]
owner["one owner · bounded lifetime"]
symmetric["open then close · start then stop · guaranteed"]
halt["invariant broken · halt"]
end
subgraph execution["Execution · control flow"]
events["children emit · parents subscribe"]
monotonic["append only · never retract"]
snapshot["backtrack by reinstantiation"]
end
structural["Structural · applies to all three · observes itself"]
resource -- observe --> computation
computation --> execution
resource --> execution
execution -- feeds --> structural
structural -- feedback --> execution
```

E1·b one exchange

```mermaid
sequenceDiagram
participant Child
participant Bus as Event bus
participant Parent
Child->>Bus: emit intent · ordinal 41
Bus->>Parent: deliver
Parent-->>Bus: accept
Child->>Bus: emit intent · ordinal 42
Bus->>Parent: deliver
Parent-->>Bus: refuse · typed error, halts: false
Note over Child,Parent: the child never calls the parent · the log only grows
```

E1·c execution as types

```typescript
export interface Emitted<Intent> {
readonly ordinal: number;
readonly intent: Intent;
}

export interface Child<Intent> {
readonly emit: (intent: Intent) => Emitted<Intent>;
}

export interface Parent<Intent> {
readonly subscribe: (react: (event: Emitted<Intent>) => "accept" | "refuse") => Unsubscribe;
}

export type Failure<Code extends string> =
| { readonly ok: true }
| { readonly ok: false; readonly code: Code; readonly halts: boolean };
```

## Links to

- [Execution Core](https://banes-lab.com/records/layer/execution-core.md)
- [Computation and resource](https://banes-lab.com/software-architecture/principles/computation-and-resource.md)
- [Event-Driven Architecture](https://banes-lab.com/records/arch/event-driven-architecture.md)
- [Domain Events](https://banes-lab.com/records/arch/domain-events.md)
- [Publish/Subscribe Pattern](https://banes-lab.com/records/arch/publish-subscribe-pattern.md)
- [Event Bus](https://banes-lab.com/records/arch/event-bus.md)
- [Observer Pattern](https://banes-lab.com/records/arch/observer-pattern.md)
- [Asynchronous Communication](https://banes-lab.com/records/arch/asynchronous-communication.md)
- [Append-Only Log](https://banes-lab.com/records/arch/append-only-log.md)
- [Event Sourcing](https://banes-lab.com/records/arch/event-sourcing.md)
- [Memento Pattern](https://banes-lab.com/records/arch/memento-pattern.md)
- [Causality](https://banes-lab.com/records/arch/causality.md)
- [Lamport Clocks](https://banes-lab.com/records/arch/lamport-clocks.md)
- [Vector Clocks](https://banes-lab.com/records/arch/vector-clocks.md)
- [Hybrid Logical Clocks](https://banes-lab.com/records/arch/hybrid-logical-clocks.md)
- [Event Ordering](https://banes-lab.com/records/arch/event-ordering.md)
- [Happens-Before Relationship](https://banes-lab.com/records/arch/happens-before-relationship.md)
- [Error Handling](https://banes-lab.com/records/arch/error-handling.md)
- [Inconsistent Error Model](https://banes-lab.com/records/arch/inconsistent-error-model.md)
- [Exception Control Flow](https://banes-lab.com/records/arch/exception-control-flow.md)
- [Fail Fast](https://banes-lab.com/records/arch/fail-fast.md)
- [Defensive Programming](https://banes-lab.com/records/arch/defensive-programming.md)
- [Fail at the boundary](https://banes-lab.com/disciplined-methodology/build/fail-at-the-boundary.md)
- [Fail Safe](https://banes-lab.com/records/arch/fail-safe.md)
- [Fail Secure](https://banes-lab.com/records/arch/fail-secure.md)

## Linked from

- [Fail at the boundary](https://banes-lab.com/disciplined-methodology/build/fail-at-the-boundary.md)
