A **C4 deployment diagram** is the fourth level of the C4 model. It shows where each container from the Container diagram actually runs — which region, availability zone, cluster, and managed service — along with replica counts, traffic routing, data replication, and network security boundaries.
Table of contents
- What is a C4 deployment diagram?
- Deployment view vs container diagram
- Elements of a deployment diagram
- How to build a deployment diagram
- Example 1: E-commerce platform on AWS
- Example 2: Banking app multi-region DR
- Example 3: SaaS platform on Kubernetes (GKE)
- Example 4: Ride-sharing active-active multi-region
- Example 5: Healthcare HIPAA-compliant deployment
- Common mistakes
- Deployment diagrams as compliance evidence
- Tooling
- Frequently asked questions
Need the full sequence, not only deployment? Start with the C4 model hub to move from the main guide into the Context, Container, and Deployment views in order.
Key takeaways
- A deployment diagram shows where containers run and how the runtime environment is wired.
- It is the C4 view that makes availability zones, regions, replicas, and failover visible.
- It should show traffic routing, data replication, and security boundaries, not just compute nodes.
- Production needs its own deployment diagram. Staging and development often need separate ones too.
- The best deployment diagrams help with incident response, reliability reviews, capacity planning, and compliance.
What is a C4 deployment diagram?
A C4 deployment diagram shows how the containers from the Container diagram are mapped onto the physical or virtual infrastructure on which they run. It answers the question: Where does this system actually live, and how is it configured to run reliably?
The deployment view has two primary concerns that distinguish it from all other C4 diagrams.
Physical placement. Where does each container run? On which node, in which cluster, in which availability zone, in which region? Physical placement determines failure domains — which components fail together and which fail independently.
Operational configuration. How many replicas are running? How is traffic distributed? What are the scaling policies? How is data replicated? These operational details determine the system's availability, performance, and resilience characteristics.
This matters more than ever. Modern systems often run across multiple availability zones, multiple regions, container orchestration platforms, managed databases and caches, and CDNs with global load balancers. That topology is hard to understand from prose alone. A deployment diagram makes it visible.
The Context diagram shows the world around a system. The Container diagram shows the system's logical structure. Neither answers the questions people ask during a real incident:
- Where is this service actually running?
- Which infrastructure does it depend on?
- What breaks if one availability zone fails?
- How many replicas are live right now?
- How does traffic enter the system and move between services?
The deployment diagram answers those questions.
Deployment view vs container diagram
The deployment diagram does not replace the Container diagram. It complements it.
| Container diagram | Deployment diagram | |
|---|---|---|
| Answers | What are the system's building blocks? | Where do those building blocks run? |
| Shows | Containers and their logical relationships | Deployment nodes, replicas, traffic routing |
| Audience | All developers and architects | DevOps, SRE, platform engineers, on-call |
| Detail level | Technology and responsibility | Infrastructure, scaling, replication |
Every container in the Container diagram should appear in at least one deployment diagram — typically the production one. Conversely, every deployable unit in the deployment diagram should correspond to a container in the Container diagram. That one-to-one connection is what makes the C4 model useful as a hierarchy.
Multiple deployment diagrams for multiple environments
A system usually has more than one environment: production, staging, development, load testing, and disaster recovery. Each environment can have a different topology — production might be multi-region, staging single-region, development running locally in Docker Compose.
Each distinct topology deserves its own deployment diagram. This is not duplication. The diagrams describe different reliability and failure characteristics. Production is the most important and should always be accurate enough for incident response, reliability reviews, security review, and onboarding.
Elements of a deployment diagram
Deployment nodes
A deployment node is a computational infrastructure element on which containers or other deployment nodes can be deployed. Deployment nodes include:
- Physical servers and virtual machines (EC2, GCE, Azure VM)
- Container orchestration clusters (Kubernetes, ECS, Nomad)
- Individual cluster nodes (Kubernetes worker nodes, ECS container instances)
- Managed cloud services (RDS, Cloud SQL, ElastiCache, Memorystore)
- Cloud regions and availability zones (us-east-1, eu-west-1, us-east-1a)
- CDN edge networks (CloudFront, Cloudflare, Akamai)
Deployment nodes are nested. A Kubernetes cluster contains worker nodes, which contain pods, which contain containers. A cloud region contains availability zones, which contain clusters. This nesting reflects the real-world infrastructure hierarchy and is where the availability and failure domain information lives.
Infrastructure nodes
An infrastructure node is a supporting element that is not a container but is relevant to the deployment architecture. Infrastructure nodes do not host containers — they provide supporting services.
Examples include load balancers (ALB, GCLB, Azure Application Gateway), DNS (Route 53, Cloud DNS), firewalls and security groups, API gateways as managed services, VPNs and private connectivity (Direct Connect, ExpressRoute), and certificate managers (ACM, Let's Encrypt).
Container instances
Containers from the Container diagram appear inside deployment nodes to show where they are running. In the deployment diagram, a container is shown as a concrete instance on specific infrastructure — not a logical concept.
Container instances should be annotated with replica count or autoscaling configuration, resource configuration (memory, CPU, instance type), and health check configuration where relevant.
Relationships
Relationships in the deployment diagram describe physical connectivity — network connections, traffic routing, data replication. They should be labelled with network protocol, port numbers where operationally relevant, traffic routing rules (canary weights, round-robin), and replication configuration (synchronous vs asynchronous, lag).
How to build a deployment diagram
Step 1: choose the environment
Start with production. Label the diagram clearly — a reader picking it up must immediately know which environment they are looking at.
Step 2: identify the infrastructure topology
Document: which cloud provider and regions, which availability zones, which orchestration platform, which managed services, which load balancers, which VPCs and subnets.
Step 3: map containers to infrastructure
For each container in the Container diagram: where it runs, how many replicas, how it scales, what resource configuration, what health checks.
Step 4: document the traffic flow
Trace how traffic enters the system: where DNS resolves, which CDN or load balancer receives requests, how requests route to container instances, how requests route between containers.
Step 5: document data replication
For every data store: primary-replica setup, synchronous vs asynchronous replication, replicas across AZs or regions, RPO implied by replication lag.
Step 6: annotate failure domains
Ask: If this availability zone goes down, what breaks? Group components by availability zone, show which services span multiple AZs, show which data stores fail over automatically, mark single points of failure clearly.
Example 1: e-commerce platform AWS production deployment {#example-1-e-commerce-platform-aws}
Infrastructure overview
The e-commerce platform runs on AWS in us-east-1, distributed across three availability zones. It uses EKS for container orchestration, RDS for managed PostgreSQL, ElastiCache for Redis, MSK for Kafka, and CloudFront for CDN.
Deployment node hierarchy
AWS Region: us-east-1
├── CloudFront Distribution (CDN)
│ └── Web Application (React SPA) — static assets cached at edge
│
├── Availability Zone: us-east-1a
│ ├── Public Subnet
│ │ └── Application Load Balancer (ALB) — HTTPS port 443
│ └── Private Subnet
│ ├── EKS Worker Node (m5.2xlarge)
│ │ ├── API Gateway Pod (Kong) — 2 replicas
│ │ ├── Order Service Pod — 2 replicas
│ │ └── Payment Service Pod — 2 replicas
│ └── RDS Primary Instance (db.r6g.2xlarge, PostgreSQL 16)
│ ├── Orders Database (primary)
│ ├── Customer Database (primary)
│ └── Payment Database (primary)
│
├── Availability Zone: us-east-1b
│ └── Private Subnet
│ ├── EKS Worker Node (m5.2xlarge)
│ │ ├── API Gateway Pod — 2 replicas
│ │ ├── Order Service Pod — 2 replicas
│ │ ├── Product Catalog Service Pod — 2 replicas
│ │ └── Customer Service Pod — 2 replicas
│ ├── RDS Read Replica (db.r6g.xlarge)
│ │ └── Asynchronous replication from primary in us-east-1a
│ └── ElastiCache Node (cache.r6g.large)
│ └── Session Cache (Redis 7)
│
├── Availability Zone: us-east-1c
│ └── Private Subnet
│ ├── EKS Worker Node (m5.2xlarge)
│ │ ├── Notification Service Pod — 2 replicas
│ │ ├── Product Catalog Service Pod — 2 replicas
│ │ └── Customer Service Pod — 2 replicas
│ └── ElastiCache Node (cache.r6g.large)
│ └── Session Cache (Redis 7) replica of us-east-1b node
│
├── MSK Cluster (Multi-AZ, 3 brokers — one per AZ)
│ └── Message Broker (Apache Kafka)
│
└── Elasticsearch Service (3-node cluster, one node per AZ)
└── Search Index
Traffic flow
User's browser
│ HTTPS (port 443)
▼
CloudFront Distribution
│ Serves static assets from edge cache
│ Forwards dynamic API requests to ALB
▼ HTTPS (port 443)
Application Load Balancer
│ SSL termination
│ Routes /api/* to API Gateway target group
│ Health check: GET /health, 30s interval
▼ HTTP (port 8000), round-robin across 6 API Gateway pods
API Gateway (Kong)
│ JWT validation, rate limiting
│ Routes to backend services by path prefix
▼ HTTP (internal)
Order Service / Customer Service / Product Catalog Service
▼ SQL (port 5432)
RDS Primary Instance
Failure domain analysis
Single AZ failure (e.g., us-east-1a goes down): ALB routes traffic to pods in remaining AZs. EKS reschedules evicted pods. RDS fails over to standby in us-east-1b or us-east-1c (~60 seconds automatic Multi-AZ failover). MSK continues with 2 of 3 brokers. ElastiCache fails over to replica (~30 seconds). User impact: increased latency during failover (30–90 seconds), no data loss for committed transactions.
What this deployment view reveals: Multi-AZ redundancy is explicit. The public/private subnet boundary is visible. The CloudFront CDN layer shows that static assets are served from edge, not origin. The read replica signals analytics query offloading from the primary.
Example 2: banking app multi-region production deployment {#example-2-banking-app-multi-region}
Infrastructure overview
The banking mobile application is deployed across two AWS regions for high availability and DR: us-east-1 (primary) and us-west-2 (secondary). This multi-region architecture is driven by regulatory requirements and an RTO of less than 15 minutes.
Primary region: us-east-1
AWS Region: us-east-1 (Primary)
├── Route 53 (DNS with health-check-based failover)
│ ├── mobile-api.bank.com → ALB in us-east-1 (primary)
│ └── mobile-api.bank.com → ALB in us-west-2 (failover on health check failure)
│
├── AWS WAF + Shield Advanced
│ └── DDoS protection, SQL injection prevention, rate limiting
│
├── Availability Zone: us-east-1a
│ ├── ALB
│ └── Private Subnet
│ ├── EKS Worker Node (r5.2xlarge)
│ │ ├── Mobile API (BFF) Pod — 3 replicas
│ │ ├── Authentication Service Pod — 2 replicas
│ │ └── Transaction Service Pod — 3 replicas
│ └── RDS Primary (db.r6g.4xlarge, PostgreSQL 16, encrypted at rest)
│ └── Transaction Database — Multi-AZ, synchronous standby in us-east-1b
│
├── Availability Zone: us-east-1b
│ └── Private Subnet
│ ├── EKS Worker Node
│ │ ├── Mobile API (BFF) Pod — 3 replicas
│ │ ├── Account Service Pod — 2 replicas
│ │ └── Card Service Pod — 2 replicas
│ ├── RDS Standby (synchronous replication from us-east-1a primary)
│ └── ElastiCache Primary Node (r6g.xlarge, Redis 7, TLS + auth enabled)
│
├── Availability Zone: us-east-1c
│ └── Private Subnet
│ ├── EKS Worker Node
│ │ ├── Notification Service Pod — 2 replicas
│ │ └── Account Service Pod — 2 replicas
│ └── ElastiCache Replica Node
│
├── Amazon MSK (Multi-AZ, 3 brokers)
│
└── AWS PrivateLink Endpoints
├── → Core Banking System (on-premises via AWS Direct Connect)
└── → Fraud Detection System (separate AWS account, VPC peering)
Secondary region: us-west-2 (warm standby DR)
AWS Region: us-west-2 (DR warm standby)
├── ALB (inactive — only receives traffic during failover)
├── EKS Cluster (scaled to 0 pods — scaled up during failover in <10 minutes)
│ └── All pods: Mobile API, Authentication, Transaction, Account, Card, Notification
├── RDS Read Replica (asynchronous replication from us-east-1 — ~5 second lag)
│ └── Promoted to primary during failover
└── ElastiCache (empty Session Store — rebuilt from RDS on startup)
What this deployment view reveals: The DR topology is explicitly warm standby — infrastructure exists but pods are scaled to zero. The ~5 second RDS replication lag is an explicit RPO signal: in a worst-case failover, up to 5 seconds of transaction data could be lost. Direct Connect for Core Banking means PHI traffic never traverses the public internet. The three-layer security group configuration (ALB → EKS → RDS) shows defense-in-depth.
Example 3: SaaS platform Kubernetes production deployment (GKE) {#example-3-saas-platform-kubernetes}
Infrastructure overview
The SaaS platform runs on GCP using GKE in us-central1, with Google Cloud Load Balancing and Cloud CDN for global traffic routing, Cloud SQL for PostgreSQL, and Cloud Memorystore for Redis.
Kubernetes cluster architecture
GCP Project: prod-saas-platform
├── Google Cloud Load Balancing (global anycast IP)
│ ├── Cloud CDN — serves React SPA static assets from edge
│ └── HTTPS Load Balancer → GKE Ingress Controller
│
├── GCP Region: us-central1
│ ├── GKE Cluster: prod-cluster (regional, 3 AZs)
│ │ ├── Node Pool: api-pool (n2-standard-8, autoscaling 3–12 nodes)
│ │ │ └── Namespace: production
│ │ │ ├── API Server (6 pods, 2 per AZ)
│ │ │ │ ├── Liveness probe: GET /healthz, 10s interval
│ │ │ │ ├── Readiness probe: GET /ready, 5s interval
│ │ │ │ ├── Resources: 2 CPU / 4 GB RAM per pod
│ │ │ │ └── HPA: min 6, max 30, target CPU 60%
│ │ │ ├── Authentication Service (3 pods, HPA min 3, max 15)
│ │ │ ├── Billing Service (2 pods)
│ │ │ ├── Search Service (3 pods)
│ │ │ └── File Service (2 pods)
│ │ │
│ │ ├── Node Pool: worker-pool (n2-standard-4, autoscaling 2–8 nodes)
│ │ │ └── Namespace: production
│ │ │ ├── Notification Service (3 pods)
│ │ │ └── Integration Service (3 pods)
│ │ │
│ │ └── Node Pool: system-pool (n2-standard-2, 3 nodes, fixed)
│ │ └── Ingress controller, Cert Manager, Prometheus, Grafana, Jaeger
│ │
│ ├── Cloud SQL (db-custom-16-65536, PostgreSQL 16)
│ │ ├── Primary: prod-primary (us-central1-a)
│ │ └── Read Replica: prod-replica-1 (us-central1-b) — reporting queries
│ │
│ ├── Cloud Memorystore (Redis 7, Standard Tier)
│ │ ├── Primary: prod-redis-primary (us-central1-a, 16 GB)
│ │ │ ├── Job Queue (Bull)
│ │ │ └── Real-Time Cache
│ │ └── Replica: prod-redis-replica (us-central1-b, auto-failover ~30s)
│ │
│ └── Google Cloud Pub/Sub
│ └── Analytics Event Stream → BigQuery export
│
└── Global Resources
├── Cloud Storage: prod-attachments (multi-region US, versioning enabled)
├── Elasticsearch Service (Elastic Cloud, 3-node cluster)
└── Secret Manager (database credentials, API keys)
Namespace and resource isolation
Kubernetes Namespaces:
├── production Live customer workloads
├── staging Pre-production validation
├── monitoring Prometheus, Grafana, Jaeger, AlertManager
├── ingress Nginx ingress controller
└── cert-manager Certificate lifecycle management
Resource Quotas (production namespace):
├── CPU limit: 80 cores
├── Memory limit: 160 GB
└── Pod limit: 200
Network Policies (production namespace):
├── Default: deny all ingress and egress
├── Allow: ingress from ingress namespace (HTTP)
├── Allow: egress to Cloud SQL (port 5432)
├── Allow: egress to Cloud Memorystore (port 6379)
└── Allow: egress to Google APIs (HTTPS port 443)
What this deployment view reveals: Three node pools with distinct purposes prevent a traffic spike on api-pool from starving system components or workers. HPA configuration communicates specific availability commitments: minimum 6 pods always available, scales to 30 at peak. The Cloud SQL Auth Proxy sidecar explains why database connections go to localhost rather than a hostname. Network policies show a zero-trust default-deny posture.
Example 4: ride-sharing active-active multi-region deployment {#example-4-ride-sharing-active-active}
Infrastructure overview
The ride-sharing platform uses an active-active multi-region deployment across three AWS regions. A complete regional failure does not interrupt service for riders and drivers in unaffected geographies.
Multi-region architecture
Global Traffic Management
├── AWS Route 53 (GeoDNS + latency-based routing)
│ ├── api.rideshare.com → us-east-1 (US East traffic)
│ ├── api.rideshare.com → eu-west-1 (European traffic)
│ └── api.rideshare.com → ap-southeast-1 (APAC traffic)
└── AWS Global Accelerator (anycast IP, TCP/UDP acceleration)
Region: us-east-1 (US Primary — active)
├── Availability Zone: us-east-1a
│ ├── EKS Worker Nodes (c5.4xlarge)
│ │ ├── Passenger API Pod — 5 replicas
│ │ ├── Driver API Pod — 5 replicas
│ │ ├── Matching Service Pod — 3 replicas (Go, high CPU)
│ │ └── Trip Service Pod — 3 replicas
│ └── ElastiCache Node (Location Store primary, r6g.2xlarge)
│
├── Availability Zone: us-east-1b
│ ├── EKS Worker Nodes
│ │ ├── Passenger API Pod — 5 replicas
│ │ ├── Driver API Pod — 5 replicas
│ │ ├── Routing Service Pod — 3 replicas (Google Maps integration)
│ │ └── Payment Service Pod — 3 replicas
│ └── ElastiCache Node (Location Store replica — async from us-east-1a)
│
├── Availability Zone: us-east-1c
│ └── EKS Worker Nodes
│ ├── Matching Service Pod — 3 replicas
│ ├── Pricing Service Pod — 3 replicas
│ └── Communication Service Pod — 2 replicas
│
├── MSK Cluster (3 brokers, replication factor 3)
│ └── Topics: TripEvents, PaymentEvents, DriverLocationUpdates
│
└── Aurora PostgreSQL (Multi-AZ)
├── Writer: us-east-1a (db.r6g.4xlarge)
├── Reader 1: us-east-1b
└── Reader 2: us-east-1c
Region: eu-west-1 (European Region — active, serves EU traffic)
├── [Same structure as us-east-1, scaled to EU traffic]
├── Aurora Global Database secondary cluster
│ └── Asynchronous replication — < 1 second lag
└── Data residency: EU PII stored only in eu-west-1 (GDPR)
└── EU data does not replicate to non-EU regions
Location service architecture
Location Service Deployment (special case — extreme performance requirements)
├── Redis Cluster (ElastiCache, cluster mode)
│ ├── 6 shards × 2 replicas = 18 nodes per region
│ ├── Geospatial index: GEOADD / GEORADIUS
│ ├── Key TTL: 30 seconds (stale drivers auto-expire)
│ └── Peak throughput: ~50,000 writes/second
│
├── Location Service Pods (Go, 10 replicas per AZ)
│ ├── Write target: <5 ms per location update
│ └── Proximity query target: <10 ms
│
└── Firebase Realtime Database
└── Driver apps write here — Location Service subscribes for events
What this deployment view reveals: Active-active is explicitly distinguished from the banking example's active-passive DR. GDPR data residency is documented as an infrastructure constraint — Aurora Global Database replication is configured to exclude PII fields for EU data. Aurora Global Database's < 1 second replication lag is a named operational commitment. The Location Service's Redis Cluster detail justifies the infrastructure investment with explicit throughput targets.
Example 5: healthcare HIPAA-compliant AWS deployment {#example-5-healthcare-hipaa}
Infrastructure overview
The healthcare portal operates in a HIPAA-compliant AWS environment. HIPAA imposes specific infrastructure requirements: encryption in transit and at rest everywhere, comprehensive audit logging, network isolation, backup and recovery procedures, and Business Associate Agreements with all cloud providers.
HIPAA-compliant architecture
AWS Region: us-east-1 (HIPAA-compliant, BAA signed with AWS)
│
├── Dedicated AWS Account for PHI workloads (account-level isolation)
│
├── VPC: 10.0.0.0/16 (HIPAA VPC — no shared resources)
│ ├── Public Subnets (10.0.1–3.0/24, one per AZ)
│ │ ├── AWS WAF (HIPAA-required: prevents injection attacks on PHI)
│ │ └── ALB (HTTPS only, TLS 1.2 minimum)
│ │
│ ├── Application Subnets (10.0.11–13.0/24)
│ │ └── EKS Worker Nodes (m5.2xlarge, HIPAA-hardened AMI)
│ │ ├── Patient Web Portal Pod — 6 total (2 per AZ)
│ │ ├── Patient API Pod — 9 total (3 per AZ)
│ │ ├── Clinical API Pod — 6 total
│ │ ├── Epic Integration Service Pod — 6 total
│ │ ├── Appointment Service Pod — 6 total
│ │ ├── Prescription Service Pod — 6 total
│ │ ├── Secure Messaging Service Pod — 6 total
│ │ ├── FHIR API Service Pod — 6 total
│ │ └── Notification Service Pod — 6 total
│ │
│ ├── Data Subnets (10.0.21–23.0/24) — no internet gateway
│ │ ├── RDS Aurora PostgreSQL (encrypted at rest, AES-256)
│ │ │ ├── Writer: us-east-1a (db.r6g.2xlarge)
│ │ │ │ ├── Patient Database (PHI — contains PII)
│ │ │ │ └── Message Store (PHI — field-level encrypted content)
│ │ │ ├── Reader: us-east-1b (reporting queries)
│ │ │ └── Automated backups: 35-day retention, encrypted, PITR enabled
│ │ │
│ │ └── ElastiCache Redis (TLS + AUTH, encrypted in transit + at rest)
│ │ ├── Primary: us-east-1a
│ │ └── Replica: us-east-1b
│ │ └── Patient Data Cache (TTL: 15 minutes)
│ │
│ ├── AWS PrivateLink Endpoints (traffic never leaves AWS network)
│ │ ├── → S3
│ │ ├── → SQS
│ │ ├── → Secrets Manager
│ │ └── → CloudWatch Logs
│ │
│ └── Transit Gateway → Hospital On-Premises Network (AWS Direct Connect)
│ └── Epic EHR System (HL7 FHIR over private connection)
│
├── AWS S3 (PHI Bucket)
│ ├── Bucket policy: deny HTTP (HTTPS only)
│ ├── Versioning: enabled (HIPAA requires version history)
│ ├── MFA delete: enabled
│ ├── Server-side encryption: AES-256
│ └── Access logging: all access logged to audit bucket
│
├── AWS CloudWatch Logs (Audit Log)
│ ├── /hipaa/phi-access — immutable resource policy, prevents deletion
│ ├── /hipaa/api-access — all API access to PHI endpoints
│ └── Retention: 7 years (HIPAA minimum), daily export to S3
│
├── AWS SQS + SNS (PHI-safe event stream)
│ ├── All queues: server-side encryption with KMS key
│ └── Message payloads: event metadata only — no PHI in message bodies
│ └── Consumers retrieve PHI via API using IDs in event payloads
│
└── AWS KMS (Customer-Managed Key: hipaa-phi-key, annual rotation)
├── Encrypts: RDS, ElastiCache, S3, SQS, CloudWatch Logs, EBS volumes
└── Key usage logged: all encrypt/decrypt operations audited
What this deployment view reveals: HIPAA compliance controls are implemented as infrastructure — the deployment diagram is the compliance evidence document. The KMS key appears as a central element encrypting every data store. PHI-free message payloads are an explicit design decision that reduces PHI surface area. Direct Connect for Epic means HL7 FHIR messages containing PHI never traverse the public internet. Immutable audit logs with 7-year retention are annotated explicitly, not described generically.
Common mistakes
The flat deployment diagram. Showing all containers as flat boxes without nesting them inside deployment nodes fails to communicate physical topology. The nesting is where the availability and failure domain information lives.
Omitting replica counts. A deployment diagram that shows a container without indicating replica count omits one of the most important pieces of operational information. A single instance is a single point of failure; ten replicas is highly available. The diagram cannot answer the question without replica annotations.
Ignoring the data layer. Deployment diagrams that show where application services run but not where databases and caches run omit the most failure-sensitive components. Database placement — which AZ, with what replication, with what backup policy — is often the most critical reliability information in the diagram.
Conflating Container and Deployment diagrams. The Container diagram shows what runs. The Deployment diagram shows where it runs. Mixing the two levels — showing Kubernetes nodes in the Container diagram, or internal service code structure in the Deployment diagram — destroys the hierarchy's usefulness.
Single-environment diagrams presented as production. Every deployment diagram must be explicitly labelled with the environment it describes. Readers making decisions based on a staging diagram assuming it reflects production will make incorrect decisions.
Omitting security and network topology. Deployment diagrams that omit load balancers, security groups, network boundaries, and VPC topology miss most of the security architecture. For regulated systems, these elements are required for the diagram to serve as compliance evidence.
Deployment diagrams as compliance evidence
For regulated systems, the deployment diagram has two jobs: it helps operators understand the runtime environment, and it helps auditors see how controls are implemented. This is common in healthcare (HIPAA), financial services (PCI-DSS), and government environments.
Auditors typically ask for diagrams showing network segmentation and data isolation, encryption in transit and at rest, access controls and authentication, audit logging configuration, and backup and recovery procedures. A well-maintained deployment diagram can answer those questions directly.
For compliance-focused diagrams, be explicit. Use "Encrypted in transit (TLS 1.2+)" and "Encrypted at rest (AES-256)" rather than just "encrypted". Use "7-year retention, immutable" for audit logs rather than "audit logging enabled". Use "No PHI in message payloads" for message queues rather than "uses SQS". This specificity is what makes the diagram useful to an auditor.
Tooling
Structurizr DSL
Structurizr supports deployment diagrams natively. The deployment node hierarchy, container instance placement, and infrastructure nodes can all be expressed as code and kept in version control alongside the system they describe.
deploymentEnvironment "Production" {
deploymentNode "AWS us-east-1" {
deploymentNode "us-east-1a" {
deploymentNode "EKS Worker Node" {
containerInstance apiGateway {
properties { "replicas" "2" }
}
containerInstance orderService {
properties { "replicas" "2" }
}
}
deploymentNode "RDS Primary" {
containerInstance ordersDb
}
}
}
}
AWS and GCP diagramming tools
AWS provides official icons for draw.io and Lucidchart. Combining AWS infrastructure icons with C4-style container and relationship notation gives you a diagram that is both cloud-specific and readable as a C4 deployment view.
Terraform and IaC as ground truth
For teams using infrastructure-as-code (Terraform, Pulumi, CloudFormation), the IaC is the authoritative source of truth. Tools like Inframap and Pluralith can generate topology diagrams from Terraform state, giving an automatic view of deployed infrastructure.
These generated diagrams are useful but not a full replacement for a maintained C4 deployment diagram — they typically miss narrative clarity, audience-focused labelling, explicit failure-domain reasoning, and operational annotations. The best pattern: IaC as source of truth, C4 deployment diagram as the human-friendly explanation.
uxxu.io
uxxu.io supports C4 deployment diagrams natively, maintaining the link between Container and Deployment views so changes to a container propagate consistently across levels.
Frequently asked questions
What is a C4 deployment diagram?
A C4 deployment diagram is the fourth level of the C4 model. It shows how the containers from the Container diagram map onto the physical or virtual infrastructure on which they run — which region, availability zone, cluster, and managed service each container is deployed to, along with replica counts, traffic routing, and replication configuration.
What is a deployment view in software architecture?
A deployment view is an architectural view that describes the physical or virtual infrastructure on which a software system runs. In the C4 model, the deployment view is the Deployment diagram — it shows where each container runs, how many replicas exist, how traffic is routed, and how data is replicated. Other architectural frameworks use similar terms: the C4 deployment view corresponds roughly to the physical view in the 4+1 architectural view model.
What is the difference between a Container diagram and a Deployment diagram?
The Container diagram shows the logical building blocks of a system — what containers exist, what each one does, and how they communicate. The Deployment diagram shows where those containers run in production — which infrastructure, how many replicas, how traffic routes between them, and how data replicates. A Container diagram exists independently of any specific infrastructure; a Deployment diagram is specific to an environment (production, staging, etc.).
What should a deployment diagram include?
A complete deployment diagram should include: deployment nodes (regions, AZs, clusters, managed services) with nesting that reflects the physical hierarchy; container instances inside deployment nodes with replica counts; infrastructure nodes (load balancers, DNS, security groups); relationships with protocol and port labels; replication configuration for all data stores; and explicit failure domain grouping by availability zone.
Do I need a separate deployment diagram for each environment?
Yes, if the environments have different topologies. Production and staging typically have different topologies — production is often multi-AZ or multi-region, staging is often single-AZ. Each distinct topology deserves its own deployment diagram, clearly labelled. If staging is topologically identical to production (rare), one diagram with environment labels can suffice.
What is a sample C4 deployment diagram?
A sample C4 deployment diagram for a web application might show: a cloud region (e.g., AWS us-east-1) containing two availability zones; each AZ containing an EKS worker node with 2 application service pods; a load balancer in a public subnet routing HTTPS traffic to the pods; an RDS primary database in AZ-a with a synchronous standby in AZ-b; and an ElastiCache Redis instance with a replica across AZs. The five examples in this guide (e-commerce, banking, SaaS, ride-sharing, healthcare) provide complete real-world sample deployment diagrams.
How often should deployment diagrams be updated?
Deployment diagrams should be updated whenever the infrastructure topology changes: new services added, scaling configurations changed, database instances resized, network topology modified, new availability zones added, or DR configuration changed. In teams using infrastructure-as-code, the deployment diagram update should be part of the same pull request as the IaC change. A stale deployment diagram is often worse than none — it creates false confidence in on-call engineers and auditors.
Conclusion
The deployment diagram is the most operational C4 view. It turns the Container diagram into a view of the real runtime environment and answers the questions that matter in production: where things run, how many instances exist, what redundancy is in place, which failure domains matter, what network controls are active, and which compliance controls are implemented.
The five examples in this guide illustrate how deployment diagrams serve different purposes in different contexts — multi-AZ redundancy, DR topology, Kubernetes resource segregation, active-active multi-region, and HIPAA compliance as infrastructure.
The key principles remain the same across all of them: show the nesting hierarchy, annotate replica counts, document replication configuration, show traffic routing, make failure domains explicit, include security topology, label the environment prominently, and keep it current.
If a system matters in production, its deployment view deserves to exist and stay accurate.
Start diagramming your deployment view in uxxu.io →