The C4 container diagram zooms inside your system boundary. It shows the applications, services, databases, and message brokers that make up your architecture — with technology labels for every building block. Level 2 of the C4 model.
A C4 container diagram is Level 2 of the C4 model. While the context diagram shows your system as a single box, the container diagram opens that box and reveals what's inside: the web applications, backend APIs, databases, message queues, caches, and other infrastructure components that compose your system.
The word “container” in C4 does not mean Docker container. It means a separately deployable or runnable unit — anything that runs in its own process space and communicates with other containers over a network. A React single-page app is a container. A Node.js API server is a container. A PostgreSQL database is a container. A Kafka cluster is a container.
Container diagrams are the most used C4 level in practice. They show the technology stack (React, Node.js, PostgreSQL), communication protocols (HTTPS, gRPC, AMQP), and deployment boundaries. Architects use them for capacity planning, DevOps engineers use them for infrastructure design, and senior developers use them for understanding service interactions.
Level 2 introduces technology labels, database shapes, and system boundaries.
An application or service within your system boundary — a web app, API, worker, or serverless function. Include the technology label.
Container(api, "API Service", "Node.js/Express", "Handles business logic and REST endpoints")A database or persistent data store. PostgreSQL, MongoDB, Redis, S3 — anything that persists state.
ContainerDb(db, "Database", "PostgreSQL", "Stores users, orders, products")A message broker or queue. RabbitMQ, Kafka, SQS — asynchronous communication between services.
ContainerQueue(queue, "Message Queue", "RabbitMQ", "Async job processing")Groups containers that belong to the same system. Everything inside the boundary is what you build and deploy.
System_Boundary(b, "Analytics Platform") { ... }An e-commerce platform showing web app, API, database, cache, and external integrations.
C4Container
title Container Diagram — E-Commerce Platform
Person(customer, "Customer", "Browses products and places orders")
System_Boundary(ecommerce, "E-Commerce Platform") {
Container(webapp, "Web App", "React/Next.js", "Product catalog, cart, checkout UI")
Container(api, "API Server", "Node.js/Express", "Business logic, order processing, REST API")
Container(worker, "Background Worker", "Node.js/Bull", "Email sending, inventory sync, report generation")
ContainerDb(db, "Database", "PostgreSQL", "Users, products, orders, inventory")
ContainerDb(cache, "Cache", "Redis", "Session store, product cache, rate limiting")
ContainerQueue(queue, "Message Queue", "RabbitMQ", "Async job dispatch")
}
System_Ext(stripe, "Stripe", "Payment processing")
System_Ext(sendgrid, "SendGrid", "Transactional emails")
System_Ext(s3, "AWS S3", "Product image storage")
Rel(customer, webapp, "Browses and buys", "HTTPS")
Rel(webapp, api, "Makes API calls", "HTTPS/JSON")
Rel(api, db, "Reads and writes data", "SQL")
Rel(api, cache, "Caches queries", "Redis protocol")
Rel(api, queue, "Dispatches async jobs", "AMQP")
Rel(worker, queue, "Processes jobs from", "AMQP")
Rel(worker, sendgrid, "Sends emails via", "API")
Rel(api, stripe, "Processes payments", "HTTPS")
Rel(api, s3, "Stores product images", "HTTPS")Paste this into Cybewave Studio to render it instantly.
@startuml
!include <C4/C4_Container>
title Container Diagram — E-Commerce Platform
Person(customer, "Customer", "Browses and buys products")
System_Boundary(ecommerce, "E-Commerce Platform") {
Container(webapp, "Web App", "React/Next.js", "Product catalog and checkout")
Container(api, "API Server", "Node.js/Express", "Business logic and REST API")
Container(worker, "Worker", "Node.js/Bull", "Background jobs")
ContainerDb(db, "Database", "PostgreSQL", "Users, orders, products")
ContainerDb(cache, "Cache", "Redis", "Sessions and caching")
ContainerQueue(queue, "Queue", "RabbitMQ", "Async messaging")
}
System_Ext(stripe, "Stripe", "Payments")
System_Ext(sendgrid, "SendGrid", "Email")
Rel(customer, webapp, "Uses", "HTTPS")
Rel(webapp, api, "Calls", "HTTPS/JSON")
Rel(api, db, "Reads/writes", "SQL")
Rel(api, cache, "Caches", "Redis")
Rel(api, queue, "Publishes", "AMQP")
Rel(worker, queue, "Consumes", "AMQP")
Rel(api, stripe, "Pays via", "HTTPS")
Rel(worker, sendgrid, "Sends email", "API")
@endumlEnumerate every deployable unit: web apps, APIs, workers, databases, caches, queues. If it runs in its own process and communicates over a network, it is a container.
Every container gets a technology label: "React/Next.js", "Node.js/Express", "PostgreSQL". This is what makes container diagrams actionable for engineers.
Group your containers inside a System_Boundary. External systems (payment gateways, email services) stay outside. This is the same boundary shown in your context diagram.
Draw Rel arrows between containers with protocol labels: "HTTPS/JSON", "gRPC", "SQL", "AMQP", "Redis protocol". Direction shows who initiates the connection.
Container diagrams are the workhorse of architecture documentation.
When your system has multiple services communicating over HTTP, gRPC, or message queues, the container diagram shows every service, its technology stack, and how they connect. Essential for understanding service dependencies before making changes.
DevOps teams use container diagrams to plan compute, storage, and networking resources. Each container maps to a deployment unit — the diagram shows what needs to scale independently and what shares infrastructure.
Replacing a database, switching from REST to gRPC, or migrating from monolith to microservices — show the current container diagram next to the proposed one. The diff makes migration scope visible.
Instead of reading pages of setup documentation, new developers see every service, database, and queue in one diagram. They understand the system topology in minutes rather than weeks.
The relationship arrows between containers define API boundaries. Each Rel label shows the protocol and data format flowing between services — the foundation for API design reviews.
After an outage, the container diagram shows blast radius. If the database goes down, which services are affected? If a queue fills up, which workers stall? Container diagrams make dependency chains explicit.
Most architecture diagrams either show too little (a context diagram with one box) or too much (every class and function crammed into a single view). Container diagrams hit the sweet spot — they show the technology stack and service topology without drowning you in module-level detail. This is why container diagrams are the most frequently created and referenced C4 level in practice.
Technology labels are what make container diagrams actionable. When a diagram says “API Server — Node.js/Express” and “Database — PostgreSQL 15”, infrastructure decisions follow directly. You know what Docker images to build, what package managers to configure, what monitoring agents to install. A box labeled just “Backend” gives you none of that information.
For evolving architectures, the container diagram becomes the source of truth for system topology. When you add a new service, decompose a monolith, or introduce a message queue, the container diagram records the change. Stored as diagram-as-code in Git, every topology change gets a PR, a review, and a permanent history. Six months later, you can trace exactly when and why each container was introduced.
A C4 container diagram is Level 2 of the C4 model. It shows the applications, services, databases, message queues, and caches inside your system boundary — plus external actors and dependencies. Each container includes a technology label and a brief description.
No. In C4, "container" means any separately deployable unit that runs in its own process space: a web app, an API, a database, a queue. It predates Docker. A single C4 container might run in a Docker container, a VM, or a serverless function — the C4 model is deployment-agnostic.
Typically 4-15 containers. If you have more than 15, consider splitting into multiple system boundaries or grouping related containers. The goal is readability — a diagram with 30 containers becomes unreadable.
Yes. Include Person (users) and System_Ext (external systems) at the edges of the diagram to show how external actors interact with your containers. They stay outside the System_Boundary.
Include the communication protocol and data format: "HTTPS/JSON", "gRPC/Protobuf", "SQL", "AMQP", "Redis protocol", "WebSocket". This helps engineers understand the integration patterns between containers.
Free to start. 50 AI credits/month. No credit card required.
Get started for free →