C4 Container Diagram: Complete Guide with Examples - Archyl Blog

The C4 container diagram (C4 model level 2) shows the deployable building blocks of your system: web apps, APIs, databases, queues. This guide explains what a container diagram is, what belongs on it, a complete worked example, common mistakes, and how to keep it in sync with your code.

C4 Container Diagram: Complete Guide with Examples

If you only ever draw one architecture diagram for your system, make it the container diagram. It's level 2 of the C4 model, and in practice it's the most used of the four levels -- because it maps directly onto the things engineering teams actually build, deploy, and operate: web apps, APIs, databases, message brokers.

This guide covers everything you need to create a good C4 container diagram: what it is (and what it isn't -- no, a C4 container is not a Docker container), what belongs on it, a complete worked example for a typical SaaS product, the mistakes that ruin most container diagrams, and how to create one manually or generate it from your codebase.

If you're new to the C4 model entirely, start with our complete guide to the C4 model, then come back here.

What Is a C4 Container Diagram?

The container diagram is level 2 of the C4 model, created by Simon Brown. It zooms into the single box that represents your system in the System Context diagram and reveals the high-level technical building blocks inside it.

In C4 terminology, a container is any separately deployable or runnable unit: something that executes code or stores data, runs in its own process (or has its own storage lifecycle), and could in principle be deployed independently of the rest of the system.

That definition covers things like:

  • A single-page application (React, Vue, Angular) running in the user's browser
  • A server-side web application (Next.js, Rails, Django)
  • A mobile application (iOS app, Android app)
  • A backend API service (Go API, Node.js server, Spring Boot service)
  • A database (PostgreSQL, MongoDB, MySQL)
  • A cache (Redis, Memcached)
  • A message broker or queue (Kafka, RabbitMQ, SQS)
  • A background worker or scheduled job process
  • A file or blob store (S3 bucket, MinIO)
  • A serverless function (AWS Lambda, Cloud Functions)

The litmus test is simple: does it run in its own process or hold its own data? Two Go packages compiled into one binary belong to the same container. Two services deployed independently are two containers -- even if they share a repository.

For a concise reference definition, see the container diagram entry in our glossary.

A C4 Container Is Not a Docker Container

This is the single most common point of confusion, so let's settle it explicitly.

The C4 model predates the mainstream adoption of Docker, and the word "container" in C4 means something broader: a runtime-level building block of your system. The overlap with Docker is coincidental and partial:

  • A C4 container might run inside a Docker container. Your Go API probably does.
  • A C4 container might run as a plain OS process, a browser tab, a mobile app, or a managed cloud service. None of those are Docker containers.
  • One Docker container could even host multiple C4 containers (an app plus an embedded database in a dev image), although that's unusual.

Put differently: Docker containers are a packaging and deployment technology. C4 containers are an architectural abstraction. A React SPA running in Chrome is a C4 container and will never be a Docker container. An RDS PostgreSQL instance is a C4 container and Docker is nowhere in sight.

When you label a box "container" on a C4 diagram, you're saying "this is a separately runnable or deployable part of my system" -- nothing more.

What Belongs on a Container Diagram

A good container diagram shows exactly three categories of information:

1. The containers themselves

Every deployable or runnable unit inside your system boundary, each labeled with its name, its responsibility, and its technology choice: "Order Service (Go)", "Session Cache (Redis)", "Web App (React SPA)". The technology label is not decoration -- it's half the value of the diagram. It's what lets a new engineer or a platform team reason about the system without opening twelve repositories.

2. The relationships and protocols

Arrows between containers, each labeled with what flows and how: "reads/writes orders (SQL)", "publishes events (AMQP)", "makes API calls (HTTPS/JSON)". Communication protocols matter at this level because they drive operational concerns -- network policies, latency budgets, retry semantics, failure modes.

3. The immediate context

The users and external systems from your context diagram, kept around the edges so the reader can see how requests enter and leave the system. You don't re-document them in detail; they're anchors.

Who is this diagram for?

The container diagram's audience is technical: developers joining the team, architects making structural decisions, and operations/platform engineers planning deployments, monitoring, and capacity. It's the level where conversations like "should these two services share a database?" or "what breaks if Redis goes down?" actually happen. Non-technical stakeholders should be looking at the context diagram instead.

What does NOT belong

  • Internal modules, classes, or packages -- those live in the component diagram (level 3)
  • Infrastructure details like load balancers, VPCs, Kubernetes nodes -- those belong on a deployment diagram
  • Every micro-interaction -- if a relationship isn't architecturally meaningful, leave it off

Container Diagram Example: A SaaS Web Product

Let's build a complete container diagram example for a fictional SaaS product -- "InvoiceHub", a web-based invoicing tool. This shape (SPA + API + database + cache + worker + queue) describes a huge share of real-world web products, so you can probably adapt it directly.

The containers

Container Technology Responsibility
Web Application React SPA The UI customers use to create and send invoices
API Application Go (Fiber) Business logic, authentication, REST API consumed by the SPA
Database PostgreSQL System of record for accounts, invoices, payments
Cache Redis Session storage and hot-path caching of invoice summaries
Message Queue RabbitMQ Decouples slow work (PDF rendering, emails) from API requests
Background Worker Go Consumes queue messages: renders PDFs, sends emails, syncs payment statuses

The relationships

[Customer] --> [Web Application (React SPA)] : Uses (HTTPS)
[Web Application] --> [API Application (Go)] : Makes API calls (HTTPS/JSON)
[API Application] --> [Database (PostgreSQL)] : Reads/writes invoices and accounts (SQL/TCP)
[API Application] --> [Cache (Redis)] : Reads/writes sessions and cached summaries (RESP)
[API Application] --> [Message Queue (RabbitMQ)] : Publishes invoice.created, email.requested (AMQP)
[Background Worker (Go)] --> [Message Queue] : Consumes jobs (AMQP)
[Background Worker] --> [Database (PostgreSQL)] : Updates job and payment status (SQL/TCP)
[Background Worker] --> [Email Service (SendGrid)] : Sends invoice emails (HTTPS/REST)
[API Application] --> [Payment Gateway (Stripe)] : Creates payment links, receives webhooks (HTTPS/REST)

What this diagram tells you

Read that list back and notice how many concrete engineering questions it answers:

  • Where does state live? Two places: PostgreSQL (durable) and Redis (ephemeral). If you've ever debated whether sessions survive a Redis restart, the diagram makes the question visible.
  • What's the failure blast radius? The worker and the API share the database. RabbitMQ down means invoices still get created but emails queue up -- by design.
  • What are the trust boundaries? The SPA runs on untrusted client devices; everything it can do goes through the API's authentication.
  • What does ops need to run? Six things, with their protocols. That's your monitoring checklist and roughly your docker-compose file.

A new developer can absorb this in two minutes. That's the entire point of C4 model level 2.

Common Container Diagram Mistakes

Most container diagrams fail in one of a few predictable ways.

Confusing containers with components

If your container diagram shows "OrderController", "InvoiceRepository", or "AuthMiddleware", you've zoomed in one level too far. Those are components -- internal building blocks inside a container -- and they belong on a level 3 component diagram. The test: can it be deployed or run on its own? A repository class cannot. Keep each diagram at one zoom level; mixing levels is the fastest way to produce an unreadable diagram.

Omitting data stores

Teams often draw only the things they wrote code for and forget that databases, caches, and queues are containers too. A container diagram without its data stores hides exactly the information architects and ops engineers need most: where state lives, what's shared, what's a single point of failure. If your system uses PostgreSQL, Redis, and S3, all three go on the diagram.

Drawing deployment instead of runtime structure

A container diagram is not an infrastructure diagram. Load balancers, Kubernetes pods, auto-scaling groups, availability zones, and the number of replicas are deployment concerns -- C4 has a separate supplementary deployment diagram for those. The container diagram answers "what are the logical runtime pieces and how do they talk?", not "how many instances run where?". Drawing three identical "API" boxes because you run three replicas adds noise, not information.

Unlabeled or vague relationships

An arrow that just says "uses" wastes the diagram's potential. "Makes API calls (HTTPS/JSON)", "publishes order events (AMQP)", "reads/writes sessions (RESP)" -- the verb and the protocol turn a picture into documentation.

Letting it rot

The most damaging mistake isn't on the diagram at all. A container diagram drawn eighteen months ago that still shows the monolith you've since split into four services actively misleads every new reader. Stale architecture documentation is worse than none -- which is why keeping the diagram synchronized with the code matters more than how pretty it is.

How to Create a Container Diagram

Manually

You can build a solid container diagram in under an hour:

  1. Start from your context diagram. Keep the users and external systems at the edges.
  2. List your deployable units. Walk through your repositories, your docker-compose file, your cloud console. Everything that runs as its own process or stores data is a candidate.
  3. Add data stores explicitly. Databases, caches, queues, blob storage.
  4. Draw the relationships. For each pair of containers that communicate, add an arrow with a verb phrase and a protocol.
  5. Label technologies. Name and tech in every box.
  6. Review with the team. The discussion this triggers ("wait, the worker talks to Stripe directly?") is usually worth more than the diagram itself.

Any tool works -- Structurizr, PlantUML with the C4 extension, draw.io, even a whiteboard. The notation matters far less than the content and the discipline of keeping it current.

With Archyl

The manual approach has one structural weakness: it captures a snapshot, and software doesn't hold still. Archyl approaches the container diagram from the opposite direction -- it derives the model from the code:

  • AI discovery from your codebase. Connect a repository and Archyl's AI discovery analyzes your code structure, configuration, and dependency manifests to propose a draft C4 model -- systems, containers, components, and the relationships between them. You review and approve the suggestions instead of drawing boxes from memory.
  • Drift detection keeps it honest. Once the model exists, Archyl continuously compares the documented containers against what the codebase actually shows and surfaces a drift score. When someone splits a service or swaps RabbitMQ for Kafka, you find out from the dashboard, not from a confused onboarding session six months later.
  • Architecture as Code. Prefer text? You can define your full C4 model -- containers, technologies, relationships -- in YAML, version it alongside your code, and let Archyl render the interactive diagrams. Diagram changes go through pull requests like everything else.

Either way, the goal is the same: a container diagram that's accurate today and still accurate next quarter.

FAQ

Is a C4 container the same as a Docker container?

No. A C4 container is an architectural abstraction: any separately deployable or runnable unit of a system, such as a web app, an API, a database, or a message broker. A Docker container is a packaging technology. Many C4 containers happen to be deployed as Docker containers, but plenty aren't -- a React SPA runs in a browser, a mobile app runs on a phone, and a managed database runs as a cloud service. The shared name is an unfortunate accident of history.

What is C4 model level 2?

Level 2 of the C4 model is the container diagram. It zooms into one software system (the single box from the level 1 context diagram) and shows the deployable/runnable units inside it, their technology choices, and the protocols they use to communicate. It sits between the context diagram (level 1) and the component diagram (level 3).

How many containers should a container diagram show?

There's no hard rule, but readability degrades quickly past 15-20 containers. If your system genuinely has more, split the view: one container diagram per subsystem, or group related containers visually. If you have hundreds, you're probably documenting multiple systems and need separate C4 models linked at the context level.

Should microservices each be a separate container?

Yes -- by definition. Each independently deployable service is its own container, along with each service's database if you follow database-per-service. That's also a useful smell test: if your "microservices" can't be drawn as separate containers because they share a process or can't deploy independently, they may be a distributed monolith.


Ready to generate your container diagram instead of drawing it? Try Archyl free and get a C4 model from your codebase in minutes. Keep exploring the C4 series: What is the C4 Model? A Complete Guide | C4 System Context Diagram Guide | C4 Component Diagram Guide.