Skip to content

Deployment Diagram

A deployment diagram shows how software systems or containers are deployed onto infrastructure for an environment such as production, staging, or development. It is useful for developers, platform engineers, and operations teams who need to understand runtime topology and network boundaries.

Supported DSL Classes

Use DeploymentDiagram with:

  • Node for a generic infrastructure boundary
  • DeploymentNode for a C4 deployment node such as a device, server, runtime, cluster, or managed service
  • Container, ContainerDb, and queue variants for deployed software
  • portable Rel

Node and DeploymentNode are portable deployment model classes. Layout variants live in contrib packages: NodeLeft and NodeRight in c4.contrib.c4_macros, and DeploymentNodeLeft and DeploymentNodeRight in c4.contrib.plantuml.

Portable Example

from c4 import Container, ContainerDb, DeploymentDiagram, DeploymentNode, Rel


with DeploymentDiagram(title="Retail production deployment") as diagram:
    with DeploymentNode("Production Cloud Account"):
        with DeploymentNode("Kubernetes Cluster"):
            api = Container("Backend API", "Handles checkout.", "Python")

        with DeploymentNode("Managed PostgreSQL"):
            db = ContainerDb("Orders Database", "Stores orders.", "PostgreSQL")

    api >> Rel("Reads and writes", "TLS / SQL") >> db

plantuml_source = diagram.as_plantuml()
mermaid_source = diagram.as_mermaid()

PlantUML enhanced example

Non-portable PlantUML example

This snippet uses PlantUML extension data, node variants, and layout helpers. Render it with the PlantUML rendering backend when keeping those hints.

The generated PlantUML example uses node tags, directional node variants, layout helpers, relationship styling, and a legend.

from c4 import (
    Container,
    ContainerDb,
    ContainerExt,
    ContainerQueue,
    DeploymentDiagram,
    DeploymentNode,
    Node,
    Person,
    Rel,
)
from c4.contrib.plantuml import (
    DeploymentNodeLeft,
    DeploymentNodeRight,
    LayD,
    LayR,
    NodeLeft,
    NodeRight,
)
from c4.renderers import (
    PlantUMLRenderOptionsBuilder,
)


with DeploymentDiagram(title='Online Shop - Production Deployment') as diagram:
    customer = Person('Customer', 'Uses the online shop through a browser.', plantuml={'tags': ['person']}, alias='customer')

    payment_gateway = ContainerExt('Payment Gateway', 'External service that processes card payments.', plantuml={'tags': ['external_service']}, technology='HTTPS API', alias='payment_gateway')

    with Node('AWS Production Account', 'Production cloud account for the online shop.', plantuml={'tags': ['cloud_account'], 'type': 'Cloud Account'}, alias='aws_prod'):
        with NodeLeft('Public Subnet', 'Internet-facing network segment.', plantuml={'tags': ['public_network'], 'type': 'Network Segment'}, alias='public_subnet'):
            with DeploymentNodeLeft('Application Load Balancer', 'Terminates TLS and routes requests to the web tier.', plantuml={'tags': ['edge_node'], 'type': 'Ingress'}, alias='alb') as alb:
                web_app = Container('Web Application', 'Serves the storefront UI.', plantuml={'tags': ['frontend']}, technology='Next.js', alias='web_app')

        with NodeRight('Private Subnet', 'Internal network segment for application and data services.', plantuml={'tags': ['private_network'], 'type': 'Network Segment'}, alias='private_subnet'):
            with DeploymentNode('Kubernetes Cluster', 'Runs backend services and asynchronous workers.', plantuml={'tags': ['runtime_node'], 'type': 'Runtime Environment'}, alias='app_cluster') as app_cluster:
                backend_api = Container('Backend API', 'Handles catalog, checkout, and order processing.', plantuml={'tags': ['backend']}, technology='Python / FastAPI', alias='backend_api')

                order_events = ContainerQueue('Order Events', 'Internal asynchronous event stream.', plantuml={'tags': ['message_bus']}, technology='Kafka', alias='order_events')

            with DeploymentNodeRight('Managed PostgreSQL', 'Managed relational database service.', plantuml={'tags': ['data_node'], 'type': 'Data Platform'}, alias='db_service') as db_service:
                orders_db = ContainerDb('Orders Database', 'Stores orders, payments, and fulfillment data.', plantuml={'tags': ['database']}, technology='PostgreSQL', alias='orders_db')

    customer >> Rel('Uses', technology='HTTPS', plantuml={'tags': ['encrypted_traffic']}) >> alb
    alb >> Rel('Routes traffic to', technology='HTTPS', plantuml={'tags': ['encrypted_traffic']}) >> app_cluster
    app_cluster >> Rel('Reads and writes', technology='TLS / SQL', plantuml={'tags': ['encrypted_traffic']}) >> db_service
    app_cluster >> Rel('Calls', technology='HTTPS/JSON', plantuml={'tags': ['encrypted_traffic']}) >> payment_gateway
    backend_api >> Rel('Publishes events to', technology='Kafka', plantuml={'tags': ['async_flow']}) >> order_events
    LayR(customer, alb)

    LayR(alb, app_cluster)

    LayD(app_cluster, db_service)

    LayR(app_cluster, payment_gateway)


plantuml_render_options = (
    PlantUMLRenderOptionsBuilder()
    .layout_left_right(
        with_legend=True,
    )
    .show_legend(
        hide_stereotype=False,
        details='Normal',
    )
    .update_legend_title(
        'Deployment Legend',
    )
    .show_person_outline()
    .show_person_sprite(
        'person',
    )
    .add_person_tag(
        tag_stereo='person',
        bg_color='#e8f5e9',
        font_color='#1b5e20',
        border_color='#66bb6a',
        shadowing=False,
        legend_text='End user',
        border_style='SolidLine',
        border_thickness='2',
    )
    .add_external_container_tag(
        tag_stereo='external_service',
        bg_color='#f3e5f5',
        font_color='#4a148c',
        border_color='#ab47bc',
        shadowing=False,
        legend_text='External service',
        border_style='DashedLine',
        border_thickness='2',
    )
    .add_container_tag(
        tag_stereo='frontend',
        bg_color='#e3f2fd',
        font_color='#0d47a1',
        border_color='#42a5f5',
        shadowing=False,
        legend_text='Frontend container',
        border_style='SolidLine',
        border_thickness='2',
    )
    .add_container_tag(
        tag_stereo='backend',
        bg_color='#ede7f6',
        font_color='#311b92',
        border_color='#7e57c2',
        shadowing=False,
        legend_text='Backend container',
        border_style='SolidLine',
        border_thickness='2',
    )
    .add_container_tag(
        tag_stereo='database',
        bg_color='#fff3e0',
        font_color='#e65100',
        border_color='#fb8c00',
        shadowing=False,
        legend_text='Database container',
        border_style='SolidLine',
        border_thickness='2',
    )
    .add_container_tag(
        tag_stereo='message_bus',
        bg_color='#fce4ec',
        font_color='#880e4f',
        border_color='#ec407a',
        shadowing=False,
        legend_text='Message queue / stream',
        border_style='SolidLine',
        border_thickness='2',
    )
    .add_node_tag(
        tag_stereo='cloud_account',
        bg_color='#eef6ff',
        font_color='#0d47a1',
        border_color='#64b5f6',
        shadowing=True,
        shape='RoundedBoxShape',
        type_='Infrastructure',
        legend_text='Cloud account boundary',
        legend_sprite='cloud',
        border_style='SolidLine',
        border_thickness='2',
    )
    .add_node_tag(
        tag_stereo='public_network',
        bg_color='#f1f8e9',
        font_color='#33691e',
        border_color='#8bc34a',
        shadowing=False,
        shape='RoundedBoxShape',
        type_='DMZ',
        legend_text='Public network zone',
        legend_sprite='network',
        border_style='SolidLine',
        border_thickness='1',
    )
    .add_node_tag(
        tag_stereo='private_network',
        bg_color='#fbe9e7',
        font_color='#bf360c',
        border_color='#ff8a65',
        shadowing=False,
        shape='RoundedBoxShape',
        type_='Internal',
        legend_text='Private network zone',
        legend_sprite='network',
        border_style='SolidLine',
        border_thickness='1',
    )
    .add_node_tag(
        tag_stereo='edge_node',
        bg_color='#e1f5fe',
        font_color='#01579b',
        border_color='#29b6f6',
        shadowing=False,
        shape='RoundedBoxShape',
        type_='Ingress',
        legend_text='Ingress deployment node',
        legend_sprite='router',
        border_style='BoldLine',
        border_thickness='2',
    )
    .add_node_tag(
        tag_stereo='runtime_node',
        bg_color='#e8f5e9',
        font_color='#1b5e20',
        border_color='#66bb6a',
        shadowing=True,
        shape='RoundedBoxShape',
        type_='Runtime',
        legend_text='Runtime deployment node',
        legend_sprite='server',
        border_style='SolidLine',
        border_thickness='2',
    )
    .add_node_tag(
        tag_stereo='data_node',
        bg_color='#fff8e1',
        font_color='#ff6f00',
        border_color='#ffb300',
        shadowing=False,
        shape='RoundedBoxShape',
        type_='Data Platform',
        legend_text='Data deployment node',
        legend_sprite='database',
        border_style='SolidLine',
        border_thickness='2',
    )
    .add_rel_tag(
        tag_stereo='encrypted_traffic',
        text_color='#0d47a1',
        line_color='#1976d2',
        technology='TLS',
        legend_text='Encrypted communication',
        legend_sprite='lock',
        line_style='SolidLine',
        line_thickness='2',
    )
    .add_rel_tag(
        tag_stereo='async_flow',
        text_color='#4a148c',
        line_color='#8e24aa',
        technology='Kafka',
        legend_text='Asynchronous event flow',
        legend_sprite='queue',
        line_style='DashedLine',
        line_thickness='2',
    )
    .update_rel_style(
        text_color='#37474f',
        line_color='#546e7a',
    )
    .build()
)

diagram.set_render_options(
    plantuml=plantuml_render_options,
)

Renderer Behavior

PlantUML has the most complete deployment support because C4-PlantUML provides deployment node rendering, left/right node variants, tags, sprites, and layout hints. Mermaid can render deployment-like nested nodes from the portable model, but Mermaid C4 support is experimental and lower fidelity for complex infrastructure topologies.

Generated Source and Image

Generated PlantUML source
@startuml
' convert it with additional command line argument -DRELATIVE_INCLUDE="relative/absolute" to use locally
!if %variable_exists("RELATIVE_INCLUDE")
    !include %get_variable_value("RELATIVE_INCLUDE")/C4_Deployment.puml
!else
    !include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Deployment.puml
!endif

AddPersonTag("person", $bgColor="#e8f5e9", $fontColor="#1b5e20", $borderColor="#66bb6a", $shadowing="false", $legendText="End user", $borderStyle=SolidLine(), $borderThickness="2")
AddExternalContainerTag("external_service", $bgColor="#f3e5f5", $fontColor="#4a148c", $borderColor="#ab47bc", $shadowing="false", $legendText="External service", $borderStyle=DashedLine(), $borderThickness="2")
AddContainerTag("frontend", $bgColor="#e3f2fd", $fontColor="#0d47a1", $borderColor="#42a5f5", $shadowing="false", $legendText="Frontend container", $borderStyle=SolidLine(), $borderThickness="2")
AddContainerTag("backend", $bgColor="#ede7f6", $fontColor="#311b92", $borderColor="#7e57c2", $shadowing="false", $legendText="Backend container", $borderStyle=SolidLine(), $borderThickness="2")
AddContainerTag("database", $bgColor="#fff3e0", $fontColor="#e65100", $borderColor="#fb8c00", $shadowing="false", $legendText="Database container", $borderStyle=SolidLine(), $borderThickness="2")
AddContainerTag("message_bus", $bgColor="#fce4ec", $fontColor="#880e4f", $borderColor="#ec407a", $shadowing="false", $legendText="Message queue / stream", $borderStyle=SolidLine(), $borderThickness="2")
AddNodeTag("cloud_account", $bgColor="#eef6ff", $fontColor="#0d47a1", $borderColor="#64b5f6", $shadowing="true", $shape=RoundedBoxShape(), $type="Infrastructure", $legendText="Cloud account boundary", $legendSprite="cloud", $borderStyle=SolidLine(), $borderThickness="2")
AddNodeTag("public_network", $bgColor="#f1f8e9", $fontColor="#33691e", $borderColor="#8bc34a", $shadowing="false", $shape=RoundedBoxShape(), $type="DMZ", $legendText="Public network zone", $legendSprite="network", $borderStyle=SolidLine(), $borderThickness="1")
AddNodeTag("private_network", $bgColor="#fbe9e7", $fontColor="#bf360c", $borderColor="#ff8a65", $shadowing="false", $shape=RoundedBoxShape(), $type="Internal", $legendText="Private network zone", $legendSprite="network", $borderStyle=SolidLine(), $borderThickness="1")
AddNodeTag("edge_node", $bgColor="#e1f5fe", $fontColor="#01579b", $borderColor="#29b6f6", $shadowing="false", $shape=RoundedBoxShape(), $type="Ingress", $legendText="Ingress deployment node", $legendSprite="router", $borderStyle=BoldLine(), $borderThickness="2")
AddNodeTag("runtime_node", $bgColor="#e8f5e9", $fontColor="#1b5e20", $borderColor="#66bb6a", $shadowing="true", $shape=RoundedBoxShape(), $type="Runtime", $legendText="Runtime deployment node", $legendSprite="server", $borderStyle=SolidLine(), $borderThickness="2")
AddNodeTag("data_node", $bgColor="#fff8e1", $fontColor="#ff6f00", $borderColor="#ffb300", $shadowing="false", $shape=RoundedBoxShape(), $type="Data Platform", $legendText="Data deployment node", $legendSprite="database", $borderStyle=SolidLine(), $borderThickness="2")
AddRelTag("encrypted_traffic", $textColor="#0d47a1", $lineColor="#1976d2", $lineStyle=SolidLine(), $techn="TLS", $legendText="Encrypted communication", $legendSprite="lock", $lineThickness="2")
AddRelTag("async_flow", $textColor="#4a148c", $lineColor="#8e24aa", $lineStyle=DashedLine(), $techn="Kafka", $legendText="Asynchronous event flow", $legendSprite="queue", $lineThickness="2")

UpdateRelStyle($textColor="#37474f", $lineColor="#546e7a")

LAYOUT_LEFT_RIGHT()
LAYOUT_WITH_LEGEND()
SHOW_PERSON_SPRITE("person")
SHOW_PERSON_OUTLINE()
UpdateLegendTitle("Deployment Legend")

title Online Shop - Production Deployment

Person(customer, "Customer", "Uses the online shop through a browser.", $tags="person")

Container_Ext(payment_gateway, "Payment Gateway", "HTTPS API", "External service that processes card payments.", $tags="external_service")

Node(aws_prod, "AWS Production Account", "Cloud Account", "Production cloud account for the online shop.", $tags="cloud_account") {
    Node_L(public_subnet, "Public Subnet", "Network Segment", "Internet-facing network segment.", $tags="public_network") {
        Deployment_Node_L(alb, "Application Load Balancer", "Ingress", "Terminates TLS and routes requests to the web tier.", $tags="edge_node") {
            Container(web_app, "Web Application", "Next.js", "Serves the storefront UI.", $tags="frontend")
        }
    }
    Node_R(private_subnet, "Private Subnet", "Network Segment", "Internal network segment for application and data services.", $tags="private_network") {
        Deployment_Node(app_cluster, "Kubernetes Cluster", "Runtime Environment", "Runs backend services and asynchronous workers.", $tags="runtime_node") {
            Container(backend_api, "Backend API", "Python / FastAPI", "Handles catalog, checkout, and order processing.", $tags="backend")
            ContainerQueue(order_events, "Order Events", "Kafka", "Internal asynchronous event stream.", $tags="message_bus")
        }
        Deployment_Node_R(db_service, "Managed PostgreSQL", "Data Platform", "Managed relational database service.", $tags="data_node") {
            ContainerDb(orders_db, "Orders Database", "PostgreSQL", "Stores orders, payments, and fulfillment data.", $tags="database")
        }
    }
}

Rel(customer, alb, "Uses", "HTTPS", $tags="encrypted_traffic")
Rel(alb, app_cluster, "Routes traffic to", "HTTPS", $tags="encrypted_traffic")
Rel(app_cluster, db_service, "Reads and writes", "TLS / SQL", $tags="encrypted_traffic")
Rel(app_cluster, payment_gateway, "Calls", "HTTPS/JSON", $tags="encrypted_traffic")
Rel(backend_api, order_events, "Publishes events to", "Kafka", $tags="async_flow")
Lay_R(customer, alb)
Lay_R(alb, app_cluster)
Lay_D(app_cluster, db_service)
Lay_R(app_cluster, payment_gateway)

SHOW_LEGEND($hideStereotype="false", $details=Normal())

@enduml

Deployment diagram