Skip to content

The Levels

The Levels

The component pattern manifests at six levels. Each level has its own concrete artifacts for all eight parts, but the structural roles are identical.

LevelUnitScale
L0FunctionA pure computation
L1ModuleA file grouping related functions
L2DomainA directory grouping related modules
L3PackageA versioned library with its own dependencies
L4ServiceA deployed application exposing a network API
L5SystemAn organization or platform composing services

How each part manifests

Interface — the contract consumers depend on:

LevelInterface artifactEnforcement
L0 FunctionType signature: (input: A) => BCompiler
L1 ModuleExported symbols (export function, export type)Module system
L2 Domainindex.ts re-exports + README.mdDirectory convention
L3 Packagepackage.json + public index.tsPackage manager + semver
L4 ServiceHTTP endpoints, OpenAPI spec, protobuf definitionsProtocol + API versioning
L5 SystemPublic SDK, developer portalLegal contracts, SLAs

Boundary — what the component cannot see through:

LevelBoundary mechanismWhat it hides
L0 FunctionLexical scope, purityGlobal state, I/O, other functions’ internals
L1 ModuleModule scope, unexported symbolsInternal helpers, implementation details
L2 DomainDirectory boundary, private modulesOther domains’ internals within the same package
L3 PackagePackage boundary, dependency DAGOther packages’ source code
L4 ServiceNetwork boundary, protocolOther services’ memory, state, database
L5 SystemOrganizational boundaryOther organizations’ infrastructure

Port — where dependencies are injected:

LevelPort mechanismExample
L0 FunctionFunction parameter, generic type parameter<R>(deps: R) => Effect<A, E, R>
L1 ModuleConstructor injection, factory parametercreateTracker(config: TrackerConfig)
L2 DomainProvider interface + implementations directoryinterface RegistryReader { ... }
L3 PackageProvider interface exported, implementation in consumerAgentProvider defined in methodts, implemented in bridge
L4 ServiceHTTP client, SDK, environment variableBRIDGE_URL=http://localhost:3456
L5 SystemAPI gateway, webhook registration, OAuthThird-party API keys, webhook endpoints

Domain — what the component is about:

LevelDomain artifactWhat “belongs together” means
L0 FunctionAlgebraic data types, input/output typesTypes that describe the same computation
L1 ModuleRelated functions operating on shared typesFunctions that transform the same data
L2 DomainSub-modules, subdirectoriesModules that describe the same concept
L3 PackageDomain directories (strategy/, triggers/)Directories that describe the same part of the world
L4 ServiceComposed packagesLibraries that serve the same business capability
L5 SystemComposed servicesServices that serve the same user or workflow

Architecture — how the component self-organizes its domain:

LevelArchitecture artifactWhat it determines
L0 FunctionFunction body, control flow, local bindingsHow the computation proceeds
L1 ModuleFunction ordering, private helpers, internal stateHow the module’s functions relate to each other
L2 DomainSub-module structure, internal dependency orderHow modules compose within the domain
L3 PackageDomain directories, service layers, route filesHow domains compose within the package
L4 ServicePackage composition, startup wiring, middleware stackHow packages compose into the running process
L5 SystemService topology, deployment architecture, data flowHow services compose into the running platform

Verification — how the component is proven correct:

LevelVerification mechanismExample
L0 FunctionCall with test inputs, assert outputsassert.equal(formatTokens(1500), '1.5k')
L1 ModuleImport and call with mock dependenciescreateTracker({ sessionsDir: tmpDir })
L2 DomainProvider interface with test doubleRecordingProvider captures all calls
L3 PackageTestkit: builders, assertions, harnesses@method/testkit
L4 ServiceStub server, contract test, integration environmentMock bridge HTTP server
L5 SystemStaging environment, sandbox APIPre-production deployment

Observability — what the component is doing and has done:

LevelObservability artifactWhat it reveals
L0 FunctionEffect trace / span, return metadataWhat the function computed, duration, what it called
L1 ModuleStructured log emissions, counter/gauge metricsWhat operations the module performed, rates, error counts
L2 DomainDomain event bus, audit trail, state transition logWhat happened in the domain’s lifecycle, decisions made
L3 PackageExported event stream, channel system, retrospectivesWhat the package did over time, patterns, anomalies
L4 ServiceHTTP access logs, health endpoints, dashboards, distributed tracesWhat the service is doing now, request patterns, error rates
L5 SystemCross-service traces, SLO dashboards, incident timelinesHow services interact, latency distribution, cascade failures

Documentation — co-located explanation:

LevelDocumentation artifactWhere it lives
L0 FunctionJSDoc comment + type signatureAbove the function definition
L1 ModuleModule-level comment, exported type descriptionsTop of the file
L2 DomainREADME.md in the domain directorysource/strategy/README.md
L3 Packagedocumentation/ directory with guides and decisionspackages/bridge/documentation/
L4 ServiceAPI documentation, deployment guideService repository root
L5 SystemDeveloper portal, architecture diagramsOrganization-level documentation site

The recursion

At each level, a component’s architecture is composed of components from the level below:

L5 System architecture = composed L4 Services
L4 Service architecture = composed L3 Packages
L3 Package architecture = composed L2 Domains
L2 Domain architecture = composed L1 Modules
L1 Module architecture = composed L0 Functions
L0 Function architecture = composed expressions and types

And at each level, a component’s interface is consumed by a component at the level above:

L0 Function interface → consumed by L1 Module (imports the function)
L1 Module interface → consumed by L2 Domain (re-exports via index.ts)
L2 Domain interface → consumed by L3 Package (exposes via public API)
L3 Package interface → consumed by L4 Service (wires into the application)
L4 Service interface → consumed by L5 System (integrates via protocol)

This is why the same disciplines apply at every level. A function that changes its type signature breaks its module. A module that changes its exports breaks its domain. A package that changes its public API breaks its service. A function that emits no traces is as invisible as a service with no health endpoint. The scale changes. The structure doesn’t.

Promotion and demotion

When a component outgrows its level, promote it:

SignalPromotion
A function grows complex enough to need its own types, tests, and documentationExtract to a module (L0 → L1)
A module grows enough related functions that it needs subdirectoriesExtract to a domain directory (L1 → L2)
A domain grows enough that it could have independent consumers and versioningExtract to a package (L2 → L3)
A package grows enough that it needs its own deployment and scalingExtract to a service (L3 → L4)
A service grows enough that it serves multiple organizationsExtract to a platform (L4 → L5)

The reverse also applies. A package with one module and one consumer is over-extracted — demote it to a domain directory. A domain directory with two files is over-organized — flatten it. Match the organizational overhead to the actual complexity.