The C4 component diagram zooms into a single container and reveals its internal architecture — modules, services, repositories, controllers, and their interfaces. Level 3 of the C4 model, designed for the developers who build and maintain each service.
A C4 component diagram is Level 3 of the C4 model. While the container diagram shows your system's applications and databases, the component diagram zooms into one specific container and shows what's inside: the modules, services, repositories, controllers, and middleware that compose that container.
A component in C4 is not a UI component (like a React component). It is a grouping of related functionality behind a well-defined interface — an AuthService, an OrderRepository, a PaymentProcessor, a NotificationModule. Components are the building blocks that developers work with daily inside a service.
Component diagrams are optional in C4 — you create them only for containers with significant internal complexity. A Redis cache or a PostgreSQL database does not need a component diagram. But a backend API service with twelve modules, three middleware layers, and connections to four databases absolutely benefits from one. Focus component diagrams on the containers that developers struggle to understand.
Level 3 introduces internal modules with technology labels and interface-level relationships.
A module, service, or class grouping within a container. Controllers, services, repositories, middleware — anything with a defined interface.
Component(authSvc, "Auth Service", "TypeScript", "Handles login, registration, JWT")Groups components that belong to the same container. This is the container you are zooming into from the Level 2 diagram.
Container_Boundary(api, "API Server") { ... }Database containers that components interact with. Shown outside the container boundary to indicate cross-container communication.
ContainerDb(db, "Database", "PostgreSQL", "Persistent storage")Relationships between components and external containers. Label with the method call or interface name for precision.
Rel(controller, authSvc, "Authenticates requests via", "JWT middleware")Zooming into the API Server container from the e-commerce container diagram.
C4Component
title Component Diagram — API Server
Container_Boundary(api, "API Server (Node.js/Express)") {
Component(router, "Router", "Express Router", "Maps HTTP routes to controllers")
Component(authMiddleware, "Auth Middleware", "JWT", "Validates tokens, extracts user context")
Component(orderController, "Order Controller", "TypeScript", "Handles order CRUD and checkout flow")
Component(productController, "Product Controller", "TypeScript", "Product catalog and search")
Component(userController, "User Controller", "TypeScript", "Registration, profile, preferences")
Component(orderService, "Order Service", "TypeScript", "Business logic for order processing")
Component(productService, "Product Service", "TypeScript", "Product search and filtering")
Component(authService, "Auth Service", "TypeScript", "Login, registration, JWT generation")
Component(orderRepo, "Order Repository", "Prisma", "Database access for orders")
Component(productRepo, "Product Repository", "Prisma", "Database access for products")
Component(userRepo, "User Repository", "Prisma", "Database access for users")
}
ContainerDb(db, "Database", "PostgreSQL", "Users, orders, products")
ContainerDb(cache, "Cache", "Redis", "Product cache, sessions")
System_Ext(stripe, "Stripe", "Payment processing")
Rel(router, authMiddleware, "Passes requests through")
Rel(authMiddleware, orderController, "Authenticated requests")
Rel(authMiddleware, productController, "Authenticated requests")
Rel(authMiddleware, userController, "Authenticated requests")
Rel(orderController, orderService, "Delegates to")
Rel(productController, productService, "Delegates to")
Rel(userController, authService, "Delegates to")
Rel(orderService, orderRepo, "Persists via")
Rel(orderService, stripe, "Processes payment", "HTTPS")
Rel(productService, productRepo, "Queries via")
Rel(productService, cache, "Caches results", "Redis")
Rel(authService, userRepo, "Reads/writes users")
Rel(orderRepo, db, "SQL queries")
Rel(productRepo, db, "SQL queries")
Rel(userRepo, db, "SQL queries")Paste this into Cybewave Studio to render it instantly.
Choose the container from your Level 2 diagram that has the most internal complexity. Start with your main API server or the container developers ask the most questions about.
Identify the controllers, services, repositories, and middleware. Follow your codebase structure — most well-organized services have a clear separation between routing, business logic, and data access.
Show how components call each other. Controllers call services, services call repositories, middleware intercepts requests. Label relationships with method names or patterns when precision helps.
Show how components interact with databases, caches, queues, and external services outside the container boundary. These are the integration points developers need to understand.
Component diagrams are for specific containers — not every service needs one.
Before splitting a monolithic service into smaller ones, map the component diagram to see which modules have clean boundaries and which are tightly coupled. The diagram reveals the natural seams for decomposition.
When a PR touches multiple modules in a service, the component diagram shows reviewers how those modules relate. They understand the blast radius of changes without reading every file in the diff.
Document your middleware pipeline, service layer patterns, and repository abstractions. New developers see the architecture decisions (dependency injection, CQRS, event sourcing) visually rather than inferring them from code.
When ownership of a service transfers between teams, the component diagram is the map. It shows where the business logic lives, how data flows through the service, and what external dependencies each module has.
When a service is slow, the component diagram helps trace the hot path. If the OrderService calls ProductRepository which calls the cache then the database, you can see exactly where to instrument and optimize.
Component boundaries define test boundaries. The diagram shows which components need mocks (external services) vs. real implementations (internal modules), directly informing your integration test architecture.
The gap between a container diagram (listing “API Server — Node.js”) and reading actual source code is enormous. A container with 200 files, 15,000 lines of code, and 40 modules is opaque from the outside. The component diagram bridges this gap by showing the architectural skeleton of a service — the major modules, their responsibilities, and how they connect — without requiring anyone to read code.
Component diagrams also enforce architectural discipline. When you draw a diagram showing that controllers should only call services (never repositories directly), and services should only call repositories (never controllers), you have a visual contract. When code violates this contract, the diagram makes the violation obvious. Teams that maintain component diagrams tend to have cleaner separation of concerns because the expected architecture is explicit.
For complex services, the component diagram becomes the entry point for every conversation about internal structure. Should we add caching to the product search? Check the component diagram — ProductService already connects to Redis through ProductCache. Should we add a new payment provider? The diagram shows exactly where PaymentService plugs into the order flow. Every “where does this go?” question has a visual answer.
A C4 component diagram is Level 3 of the C4 model. It shows the internal structure of a single container — the modules, services, repositories, and controllers inside that service and how they interact with each other and external containers.
No. Only create component diagrams for containers with significant internal complexity — typically your main API services. Databases, caches, and queues do not need component diagrams. Focus on the 2-3 containers that developers find hardest to understand.
Components should be at the module or service level — not individual classes or functions. A good rule: each component should map to a folder or namespace in your codebase. If you have more than 15 components, you may be too granular.
No. In C4, "component" means a module or service grouping with a defined interface — like an AuthService, OrderRepository, or PaymentProcessor. React components are UI building blocks at a completely different level of abstraction.
A component diagram is one zoom level above a class diagram. Components group related classes and functions behind an interface. If you need to see individual classes and their relationships, that is C4 Level 4 (Code) — which most teams skip since it can be auto-generated from code.
Free to start. 50 AI credits/month. No credit card required.
Get started for free →