C2: Containers and Services

A C2 diagram opens one or more systems and shows their main logical runtime units: applications, services, and processes that collaborate to provide the system's behavior. A model that does not describe deployment in detail may also represent supporting resources such as a database or broker as C2 containers. When a detailed deployment model is planned, those infrastructure elements are better placed in the Deployment view, while C2 remains focused on the logical parts of the system that use them.

Containers and services

Container and Service represent the same architectural level. Both are selected as ContainerElement, can own components, participate in relationships, and connect the logical model to deployment infrastructure.

The two constructors provide a choice of vocabulary. container is the general C4 term for an executable or deployable unit. service is useful when the element has an independently understandable service responsibility, such as a backend service, an API, or a platform capability:

system commerce
    name = Commerce

    container storefront
        name = Storefront application
        technology = React

    service catalog
        name = Product catalog
        technology = Kotlin

This distinction helps the source describe intent without introducing another diagram level. A service remains a container in the type system and appears beside other containers in the same C2 view.

The C2 view

The default C2 view is centered on the selected tab. It includes the containers and services declared or extended by that tab, together with their relationship neighborhood. Related containers from the same system are placed inside the same system boundary even when their declarations are kept in other files. Unrelated containers remain outside the selected diagram.

All systems opened by the selected tab form one C2 focus. Their containers and services are internal to the complete diagram, including content contributed to those systems through extend. When a relationship leaves that focus, the closed system at the other end is shown as an external endpoint. Its containers and components remain hidden, so the diagram does not expose the internals of a system it has not opened.

Components remain folded into their container at C2. Their relationships can still contribute to the view: when a component-level dependency crosses container boundaries, it can be lifted to the containers that own its endpoints.

Relationship ownership and direction

A wire belongs to the element under which it is declared. That element is the source of the relationship, and the element written after the operator is its target:

service checkout
    name = Checkout
    links:
        -> catalog
            description = Reads product information

Here, checkout owns the dependency and the diagram draws checkout → catalog. Placing the same declaration under catalog would draw catalog → checkout. The operator describes the interaction style, while the declaration position establishes its direction.

The same rule applies to asynchronous dependencies. In a publish-and-subscribe
flow, the consumer owns the dependency on the producer's event stream:

service order_fulfillment
    links:
        ~> checkout
            description = Consumes completed order events
            via = orders.completed

The arrow starts at order_fulfillment because that service must react to the
event and therefore owns the dependency. checkout is the producer, while
via names the topic or channel that carries the interaction. The ~> operator
changes the relationship to asynchronous and gives it the corresponding
presentation; it does not reverse the source and target.

Relationships pushed to C1

Relationships declared at C2 are lifted to the systems that own their endpoints when a C1 diagram is built. A dependency from checkout inside the commerce system to payments_api inside the payments system produces a derived commerce → payments relationship at C1.

This makes the C2 declaration the best source of truth when the real dependency belongs to a particular container or service. The C1 view receives the broader interaction automatically and the C2 view retains its precise endpoints.

Once a relationship is described at C2, the equivalent C1 relationship should usually be removed. Keeping both declarations gives the model two accounts of the same dependency. It may produce duplicate-looking arrows, create ambiguity about which declaration owns the meaningful attributes, and cause the system-level edge to shadow the lower-level edge. Archinsight reports this shadowing so the broader declaration can be removed and the relationship can flow upward from its most precise level.

A separate C1 relationship remains useful when it expresses a genuinely different system-level interaction that has no more precise owner below it.

Connecting C2 to deployment

C2 is where logical architecture begins to connect naturally to deployment. Containers and services are the units that run on compute resources, use infrastructure, and are assigned to deployment profiles. Their logical wires can also be mapped onto network connections and physical paths.

Deployment information can be attached to an element:

service catalog
    name = Product catalog

    deployment:
        uses production_service

The selected profile supplies the deployment environment together with values such as runsOn and uses. These values connect the service to the compute, storage, broker, or other infrastructure that supports it.

A wire has its own deployment information because the path between two deployed elements may require infrastructure of its own. A logical dependency can use a network connection, gateway, broker, or another physical route without changing the logical source and target of the wire.

This creates two related deployment paths:

  • element deployment places a container or service onto infrastructure and records the infrastructure it uses;
  • edge deployment explains how a logical wire is carried through infrastructure between its deployed endpoints.

The C2 model remains the logical description. Deployment views expand these declarations into physical elements and projected relationships.

C2 entities

The C2 vocabulary contains one abstract type and two concrete types at the same modeling level.

Entity Constructor Purpose
ContainerElement Abstract common type selected by C2 views.
Container container General executable or deployable unit inside a system.
Service service A container described specifically as a service or independently understandable capability.

Container attributes

Name Type Required Meaning
name Text No Human-readable name shown on the diagram.
technology Text No Main implementation technology or runtime.
description Text No Responsibility of the container within its system.
links List of Wire No Outgoing relationships owned by the container. Each arrow starts at this container and points to the referenced target.
_ List of Component No Anonymous list of components owned by the container and shown at C3.

Service attributes

Service inherits every Container attribute and strengthens the name contract:

Name Type Required Meaning
name Text Yes Human-readable service name.
technology Text No Main implementation technology or runtime.
description Text No Responsibility provided by the service.
links List of Wire No Outgoing relationships owned by the service. Each arrow starts at this service and points to the referenced target.
_ List of Component No Anonymous list of components owned by the service and shown at C3.

Deployment attributes inherited by C2 elements

All Element descendants receive the built-in deployment attributes, so they are available on both containers and services.

Name Type Required Meaning
deployment List of Edge No Deployment actions, commonly the selection of a DeploymentProfile through uses.
runsOn InfrastructureComponent No Infrastructure that hosts the deployed element.
uses List of InfrastructureComponent No Storage, brokers, network resources, or other infrastructure required by the element.

C2 relationship attributes

The C2 level uses the same Wire family as C1. The declaration owner is always the source of the wire.

Name Type Required Applies to Meaning
technology Text No ->, ~> Protocol, transport, or integration technology.
description Text No ->, ~> Purpose of the interaction.
model WireModel Yes, provided by constructor ->, ~> Enum value identifying the relationship as sync or async for queries. The built-in constructor supplies it.
deployment List of Edge No ->, ~> Deployment actions that describe the physical realization of the wire.
uses List of NetworkConnection No ->, ~> Network capabilities used by the deployed relationship.
call Text No -> Operation or interface invoked by a synchronous interaction.
via Text No ~> Topic, channel, queue, or route used by an asynchronous interaction.
Quick Navigation