An Ecore micro-model of the C4 vocabulary: Person, System, Container, Component, Code, each a two-line specialization of the architecture model’s Element, plus three derived references that let you navigate the C4 levels without maintaining a second containment tree.

That is the whole model. There is no C4 relationship class, no C4 diagram class, and no C4 workspace: an arrow between two C4 elements is the architecture model’s Relationship, typed by a RelationshipKind from whatever catalog the estate uses, and a diagram is a generated view rather than a stored artifact.

A floor you can walk past

C4 sits above architecture in the micro-model tower for three reasons, and one of them is an opinion.

It is tiny - five classes, three derived references, no attributes of its own - so putting it in the tower costs the floors above it a dependency of a few kilobytes rather than a metamodel commitment.

It is popular - the most widely understood decomposition vocabulary in software, taught, drawn, and argued about far more than ArchiMate or TOGAF - which means naming an estate element a Container communicates more, to more people, than any vocabulary this project could invent.

And it can be ignored. Nothing below C4 knows it exists, and an upper floor that has no use for the levels simply extends Element directly, as the threat model’s Asset does. That is the opinionated part: a floor earns its place in the tower by being cheap to inherit and free to skip, and C4 is the clearest instance of the rule. Take it if the four levels help you explain your estate. Walk past it if they do not - but do not stop on this floor on the way to somewhere else.

Kinds or classes?

The architecture model already says that C4 can be loaded as an ElementKind catalog, and that remains true and remains the right move when C4 is a notation you are adopting - drawing an estate, tagging elements, generating context diagrams. Kinds are data: a catalog is authored once, versioned, shipped as a Maven artifact, and swapped for ArchiMate next quarter without a metamodel release.

Classes are for when an upper floor wants to extend a level rather than tag it. A Tibco BW5 EAR is not merely tagged as a container - it is a container, with EAR-specific features of its own, and the model above wants class Ear extends Container. That is what this floor supplies: typed base classes, so instanceof, generated Java accessors, and level-aware documentation generation all work, and so an estate model gets the C4 reading for free instead of hand-tagging every parsed element.

The two coexist. kind stays available on every C4 element and carries the vocabulary a class cannot: technology (“Java 21, Spring Boot”, “PostgreSQL 16”), scope (“internal system”, “external system”, “SaaS”), taxonomy (“a microservice is a kind of container”). Those are instance data on purpose - burning technology and external into the metamodel is precisely the mistake that leaves everyone with a free-text field and no way to ask which containers run an out-of-support runtime.

Derived views, one tree

C4’s levels are a decomposition, and the architecture model already has decomposition: Element.elements. Rather than give each level its own containment reference - which would mean five parallel trees, five places to look for an element, and an authoring surface that has to guess which one you meant - each level exposes a derived, filtered, live view of the one tree:

Level View Backed by
System containers Element.elements
Container components Element.elements
Component code Element.elements

The views are backed by DerivedSubsetEList, so they are modifiable as well as readable: adding a Container through system.containers writes through to elements with the backing feature’s own containment, opposite, and notification semantics intact, and dispatches a notification against the derived feature too. Nothing is cached and nothing is serialized - the views are derived transient volatile, computed on access, so they cannot drift from the tree they filter.

The consequence worth naming is what the views deliberately do not hide. A system may contain elements that are not containers - a nested System, a Person, a plain architecture Element used as a grouping folder, an ElementReference to a federated system - and those remain full members of elements. The C4 reading is a lens over the containment tree, not a constraint on it, which is what lets a strict C4 view and a messy real estate live in the same model.

Competitive landscape

Structurizr. The reference implementation, by C4’s author, and the direct comparison. Its DSL is excellent. But the workspace is the unit and the silo: the metamodel is fixed, there is no aspect composition, and federation across workspaces stops at links. Here C4 is a lens on elements that are already workable, governed, staged, access controlled, owned, and provenance carrying, and federation is an ElementReference in the floor below.

LikeC4, C4-PlantUML, Mermaid C4, diagrams-as-code generally. Text-authored C4 with generated pictures, and genuinely pleasant to use. They model a diagram, though - the file is a drawing whose subject happens to be architecture. The distinction shows up the first time you want to ask a question that is not a picture: which components a CVE reaches, which containers a data residency control applies to, what a decommissioning would disturb. This model has no diagram class at all; diagrams are one generated rendering among several, via the Draw.io or other writable diagram models.

IcePanel and the C4 SaaS tools. Collaborative, pleasant, and centralized: the model lives in the vendor’s database, versioning is theirs, and the crosswalk to risk, control, ownership, and work is manual or absent - the same critique the tower makes of EA and GRC platforms. Here the model is Ecore in Git, and the crosswalks are inheritance and references.

ArchiMate / Archi. Sixty-odd element types that practitioners subset anyway, versus C4’s four that practitioners already know. This model takes the position that the small vocabulary won - and then declines to burn even that one into the base metamodel, which is why C4 is a floor above architecture rather than architecture itself.

Backstage catalog. Instructive because it is the other tiny federated model that got adopted: kind, spec, relations, as YAML in Git. Component and System are its two most-used kinds, and they are C4’s, borrowed without the levels. This is that shape with a typed metamodel underneath, so the levels are checked rather than conventional.

Applications

Base classes for estate models. The immediate use, and the reason this floor exists at all. Estate models parse real artifacts and currently declare their own structural classes; re-parenting them to C4 costs nothing and buys terminology a newcomer already understands. Tibco BW5 reads clearly this way: an EAR is a Container (the deployable, runnable unit), a project is a Component (grouped functionality behind an interface, not separately deployable), and process definitions, schemas, and shared resources are Code. A Maven module is a Component, and the artifact it produces may well be a Container.

The payoff is not naming for its own sake: once an estate is typed at C4 levels, a cross-technology question - “show me every container in the payments domain, whatever it is built in” - is one query over one vocabulary rather than one query per estate model.

Generated documentation at the right altitude. Level-aware generation falls out of the derived views: a system page lists containers, a container page lists components, and the “zoom in” navigation everyone hand-maintains in Confluence becomes the containment tree with a filter on it.

C4 with the aspects attached. A container that carries its risks, its controls, its lifecycle stage, its owner, its open work, and its cost is not something C4 tooling offers, and it is not something this floor implements - it is what the floors below already deliver to every Element. The C4 diagram and the audit pack are then two views of one graph.

Threat modeling at container granularity. Asset extends Element in the threat model, so C4 elements are assets. Trust boundaries drawn across containers, and data flows over the architecture model’s reified relationships, give the STRIDE-per-element exercise a substrate the architecture team is already maintaining.

Model overview

Area Types
Base imported from the floor below: threat Asset (transitively Element, Workable, Governed, Staged, nxcore ModelElement)
Levels System (L1), Container (L2), Component (L3), Code (L4)
Actors Person
Derived views System.containers, Container.components, Component.code - modifiable subsets of Element.elements via DerivedSubsetEList
Reused, not redefined architecture Relationship and RelationshipKind (arrows), ElementKind (technology, scope, taxonomy), ElementReference (federation)

Relation to other Nasdanika work

C4 extends the threat model and adds nothing below it: System, Container, Component, Code, and Person all extend Asset, so the whole tower - nxcore < role < iam < seal < lifecycle < decision < governance < work < architecture < threat - arrives with them.

Estate and platform models are the intended consumers, re-parenting their structural classes to the level they actually represent.