A system is a node in the architecture map. A capability system is a logical unit of product value that provides capabilities; an infrastructure system is a concrete piece of the stack — a database, an event bus — that capability systems run on. The kind field decides which.
Here is Chowk's ordering capability system — the supply side of the order lifecycle:
system OrderingSystem {
title "Ordering"
kind capability
owner "chowk-ordering-team"
depends_on [infrastructure.v1.PrimaryDatabase, infrastructure.v1.EventBus]
labels { domain: "ordering" surface: "customer" tier: "critical" team: "chowk-ordering" }
doc "Chowk's checkout lifecycle: open an order, add its lines, pay, and read it back."
provides {
OrderCheckout maturity "beta"
OrderPayment maturity "beta"
OrderTracking maturity "beta"
}
metadata_type SystemMetadata
metadata {
operating_cost: 40
business_value: 10
criticality: "critical"
sla: "99.95% / p99 < 250ms"
value_statement: "Ordering is where the marketplace makes money — every checkout runs through it."
}
feature_type Feature
feature "Order lifecycle" { consumer "customer" maturity "beta" category "ordering" description "…" value 10 }
}provides — the supply side
provides { <Capability> maturity "<reality>" } is how a system declares the capabilities it supplies. This is the counterpart to a business_process step's requires: match the two and the realizing system is derived. Note the provision maturity is the realization reality — distinct from the capability node's declared intent — so a capability planned at ga can honestly advertise that only its beta implementation ships today.
A system need not provide the composite of capabilities it supplies: because OrderingSystem provides all three order-lifecycle leaves, the OrderManagement composite is satisfied for free by the roll-up.
kind — capability vs infrastructure
kind classifies the node. It is the one fixed enum in the overlay:
kind | Meaning |
|---|---|
capability | A logical unit of product value (the default). Provides capabilities. |
database, cache, event_bus, message_queue, blob_store, search_index | Backing stores and buses. |
llm, external_api, identity_provider, service | External and service dependencies. |
An infrastructure system names its kind, its provider (the concrete technology), and what it represents (the real resource it maps to). Chowk's database:
system PrimaryDatabase {
title "Primary Database"
kind database
owner "chowk-platform-team"
provider "postgres"
represents ["data_store:chowk_db"]
doc "The Postgres instance every sub-domain's aggregates persist to — the marketplace's single source of truth."
metadata_type SystemMetadata
metadata { operating_cost: 800 business_value: 10 criticality: "critical" sla: "99.95% availability" value_statement: "…" }
feature_type Feature
feature "Tenant-isolated persistence" { consumer "system" maturity "beta" category "storage" description "…" value 9 }
}Capability systems then draw depends_on edges to these infrastructure nodes — the "uses" relationship (see Composition & roll-ups). An infrastructure system with no provider set draws a warning: the map wants to know what technology backs the node.
metadata_type and feature_type — typed blocks
Every system carries two free-form blocks — metadata {} (business/operational numbers and notes) and feature {} (the capabilities it ships, packaged) — and both are given a typed shape by a value object, bound with metadata_type and feature_type. Both bindings are required on every system.
By convention those two value objects — SystemMetadata and Feature — are defined once for the whole project, in a shared kernel, and imported everywhere:
value SystemMetadata "Typed business metadata attached to a system marker for diagram roll-ups." {
operating_cost double // estimated monthly operating cost; summed up the tree
business_value double // 1–10 business-value score; summed up the tree
criticality string // author-defined; not a framework field
sla string
value_statement string
}The payoff of typing them is that the blocks are checked: a metadata key that isn't on the schema fails the build rather than silently disappearing, and a numeric field added to the schema rolls up everywhere at once. (criticality here is an author-defined metadata field — a plain string, not a framework concept; only the numeric fields participate in roll-ups.)
labels — grouping dimensions
labels {} is a flat map of quoted-string keys attached to a system (and to capabilities, business processes, and journeys). It is a coarse taxonomy the overlay can slice on — not a place for measures (a number is rejected). Reuse a small, consistent key vocabulary — Chowk uses domain · surface · tier · team — across every node so the labels compose into a filterable grid.
The system-vs-feature rule
When does a new concern deserve its own system, and when is it a feature of an existing one? The test is the dependency fingerprint:
- Promote to a system when it has its own dependency fingerprint or independent criticality — its own
depends_onset, its own operational profile. - Keep it a feature when it is a behavior-variant sharing the parent's dependencies.
Chowk's whole context of ordering — placing, paying, tracking — shares one fingerprint (the same database and bus), so it is one OrderingSystem carrying several capabilities and features, not three systems. Password vs magic-link vs OTP login would likewise be features of a Login system, not systems in their own right.