Review C4 architecture models for notation compliance, completeness, and common mistakes. Use when reviewing architecture PRs, auditing existing models, validating model quality, or before publishing architecture documentation.
Installation
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Review C4 architecture models for notation compliance, completeness, and common mistakes. Use when reviewing architecture PRs, auditing existing models, validating model quality, or before publishing architecture documentation.
metadata
{"author":"Georges Martin <jrjsmrtn@gmail.com>","version":"0.1.7"}
license
MIT
C4 Review
Review C4 architecture models for notation compliance, completeness, and common mistakes.
When to Use
Reviewing a PR that modifies architecture/workspace.dsl
Auditing an existing C4 model for quality
Before publishing or sharing architecture diagrams
After significant model changes to catch regressions
When onboarding to understand if an existing model is trustworthy
Required Inputs
Path to the Structurizr DSL workspace file (typically architecture/workspace.dsl)
Optionally: the project's technology stack and deployment context for completeness checks
Workflow
Phase 1: Syntax Validation
Run structurizr/structurizr to catch syntax errors before manual review:
The exit code equals the number of violations. Severity levels can be tuned per element via structurizr.inspection.* workspace properties (ignore, info, warning, error).
Phase 3: Element Review (manual)
Check every element in the model against these criteria:
People/Actors
Every person has a clear, specific name (not "User" unless truly generic)
Every person has a description stating their role/goal
No duplicate people representing the same role
External vs internal actors are distinguished (via tags or naming)
Software Systems
Your system has a name and description
External systems are clearly identified (tagged "External" or similar)
Each external system has a description explaining what it provides
No system is modeled that should actually be a container (e.g., a database you own)
System names are unique and unambiguous
Containers
Every container represents a runtime boundary (separately running process or data store)
No libraries, modules, or packages modeled as containers
Every container has a technology specified
Every container has a meaningful description (not just restating the name)
Database containers use the "Database" tag for cylinder shape
No containers that should be external systems (services you don't own/deploy)
Components (if present)
Components represent architecturally significant groupings, not just folder structure
Every component has technology specified
Components are within a single container (not spanning containers)
The component diagram adds genuine value (if not, recommend removing it)
Phase 4: Relationship Review
Check every relationship:
Labels
Every relationship has a label describing intent (what is communicated, not just "uses")
Labels match the arrow direction (source does X to destination)
No vague labels: flag "Uses", "Connects to", "Interacts with", "Communicates with"
Completeness assessment: What's missing relative to the known system
Positive observations: What the model does well (helps calibrate quality)
Common Anti-Patterns
The "Everything Uses Everything" Model
Too many relationships with vague labels
Fix: remove implied relationships, make labels specific
The "Code Structure Mirror"
Components that exactly match package/module structure
Fix: model architecturally significant groupings, not code organization
The "Missing Middle"
System context exists but no container view, jumping straight to components
Fix: always create the container view
The "Stale Component Diagram"
Component diagram that hasn't been updated as code evolved
Fix: delete it or regenerate it; stale diagrams are worse than none
The "Docker Confusion"
Modeling Docker containers as C4 containers, or modeling C4 containers as Docker containers
Fix: C4 containers are runtime boundaries; Docker is a deployment mechanism (belongs in deployment view)
The "Technology Soup"
Container descriptions that are just technology names ("Elixir GenServer Phoenix")
Fix: descriptions should state responsibilities ("Handles user authentication and session management")
The "GenServer Container"
Individual GenServers modeled as C4 containers
Fix: GenServers are BEAM processes within a VM — they're code-level, not runtime boundaries. Model the release as the container.
The "Supervision Tree Diagram"
Component diagram that mirrors the supervision tree structure
Fix: components should represent functional groupings (Accounts, Orders, Notifications), not supervision hierarchies (Application → Supervisor → Worker)
The "Umbrella = Microservices" Model
Each umbrella app modeled as a separate C4 container or even software system
Fix: if the umbrella deploys as one release, it's one container. Model umbrella apps as components within that container. Only split into containers if they deploy as separate releases.
Erlang/Elixir/OTP Review Checklist
When reviewing a C4 model for an Elixir/OTP system, check these additional items:
Abstraction Correctness
OTP releases are modeled as containers (not individual applications or GenServers)
GenServers, Agents, Tasks are NOT modeled as containers or components (unless architecturally significant)
Supervisor trees are NOT reflected in the component structure
Umbrella apps deployed as a single release are modeled as ONE container with components, not multiple containers
Phoenix PubSub is NOT modeled as a separate message queue container
ETS tables are NOT modeled as separate database containers (they're in-process)
Container Review
Phoenix application container specifies "Elixir/Phoenix" as technology, not just "Elixir"
If Oban is embedded in the Phoenix release, it's a component, not a separate container
If Broadway is embedded, it's a component, not a separate container
Mnesia is only a separate container if it's architecturally significant and spans nodes
Nerves firmware is modeled as a container, not a software system
Relationship Review
Ecto connections specify "Ecto/TCP" or "SQL/TCP", not just "Ecto"
WebSocket connections are labeled (for LiveView, Channels)
Erlang distribution between nodes is modeled as a deployment-level relationship, not a container-level one
Oban job queues via PostgreSQL are labeled "Oban/PostgreSQL", not just "PostgreSQL"
Component Review (if present)
Components represent functional domains (Accounts, Orders, Notifications), not OTP applications or supervision trees
Phoenix contexts or Ash domains map naturally to components (they're the intended grouping mechanism)
Ecto.Repo is either a component ("Data Access") or omitted — not a separate container