Architecture as Code: Define Your Entire C4 Model in a YAML File
Architecture diagrams have a shelf life problem. You draw them after a design session, they look great for a week, and then the code evolves while the diagrams rot. Six months later, the new hire stares at a Container diagram that shows three services that were merged in Q2 and doesn't mention the two that were built in Q3.
We've been obsessed with this problem since day one at Archyl. AI discovery helps keep things fresh. The visual editor makes updates painless. But there's a class of teams — the ones that treat infrastructure as code, policies as code, everything as code — who wanted something more fundamental.
They wanted their architecture to live in Git, next to the code it describes. Today, that's exactly what we're shipping.
What Is archyl.yaml?
It's a single YAML file that declaratively describes your complete architecture. Drop it at the root of your repository, and it becomes the source of truth for your C4 model in Archyl.
Here's what a minimal file looks like:
version: "1.0"
project:
name: "My Platform"
description: "Microservices architecture"
systems:
- name: Platform
type: software_system
containers:
- name: API Gateway
type: api
technologies: [Go, gRPC]
- name: User Database
type: database
technologies: [PostgreSQL]
relationships:
- from: API Gateway
to: User Database
label: "Reads user data"
type: reads_from
That's it. Archyl reads this file, builds the full C4 model, renders diagrams, and keeps everything synchronized. No clicking through UIs, no manual syncing, no "I forgot to update the diagram."
Everything in One File
The DSL isn't a simplified subset — it covers the full scope of what Archyl can model:
All four C4 levels. Systems contain containers, containers contain components, components contain code elements. The YAML nesting mirrors the hierarchy directly.
Relationships with dot-notation. Connect any two elements using readable references like Payment Service.API Gateway → Payment Service.Database. No UUIDs, no cryptic identifiers. Greppable, diff-friendly, human-readable.
Technologies, environments, and releases. Define your technology catalog, declare deployment environments (staging, production), and track releases — all from the same file.
ADRs and documentation. Inline your Architecture Decision Records or point to a folder in your repo. Same for project documentation.
API contracts and event channels. Declare your OpenAPI specs, gRPC definitions, Kafka topics, and link them to the components that expose or consume them.
Visual overlays. Group elements on the diagram with named overlays, controlling colors and levels.
Monorepo support. Use include to split your architecture across multiple files — one per service, team, or bounded context — and Archyl merges them automatically.
Why YAML?
We considered building a custom DSL syntax (like Structurizr's DSL or Terraform's HCL). We chose YAML for practical reasons:
Zero learning curve. Every developer already knows YAML. No new syntax to learn, no parser to install, no editor plugin required.
IDE support for free. We publish a JSON Schema at
/api/v1/dsl/schema. Point your IDE at it and you get autocomplete, validation, and inline documentation without any Archyl-specific tooling.Diff-friendly. YAML diffs are clean and readable in pull requests. Reviewers can immediately see "ah, they added a new container to the Payment Service and connected it to Redis."
Tool ecosystem. Linters, formatters, templating engines (Helm, Kustomize), all work with YAML out of the box.
The Git-Native Workflow
Here's where the real power is. Because archyl.yaml lives in your repository, architecture changes follow the same workflow as code changes:
- Branch. Create a feature branch, edit the YAML.
- Review. Open a pull request. Your team reviews the architecture change alongside the code change.
- Merge. Once approved, merge to main.
- Sync. Archyl picks up the change and updates the diagrams automatically.
No more "the diagram says X but the code does Y." No more architecture changes that bypass review. No more documentation that nobody knows was updated.
CI/CD Integration
We built first-class integration with CI/CD pipelines. For GitHub, we ship an official GitHub Action that handles everything — reading the file, calling the API, and reporting what changed.
GitHub Actions (official action):
name: Sync Architecture
on:
push:
branches: [main]
paths: ['archyl.yaml']
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: archyl-com/actions/sync@v1
with:
api-key: ${{ secrets.ARCHYL_API_KEY }}
project-id: 'your-project-uuid'
That's it. Three lines of config and your architecture stays in sync on every push. The action supports custom file paths (for monorepos), self-hosted Archyl instances, and exposes outputs like summary, systems-created, and relationships-created for downstream steps.
GitLab CI:
sync-architecture:
stage: deploy
script:
- |
curl -X POST \
https://api.archyl.com/api/v1/projects/$ARCHYL_PROJECT_ID/dsl/ingest \
-H "X-API-Key: $ARCHYL_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"content\": \"$(cat archyl.yaml | jq -Rs .)\"}"
only:
changes:
- archyl.yaml
The /ingest endpoint accepts API key authentication, so no OAuth flow is needed in CI. It imports the full model, creates or updates every element, and returns a detailed summary of what changed.
You can also sync directly from the Archyl UI. If your project has a connected Git repository, hit "Sync Now" in the Architecture as Code settings and Archyl fetches the file directly from your repo.
Bidirectional: Export and Import
The workflow isn't one-directional. Already have a project modeled in Archyl's visual editor? Export it:
- Export generates a complete
archyl.yamlfrom your current model. Every system, container, component, relationship, overlay, ADR, API contract, event channel, release — all serialized to clean YAML. - Import parses an
archyl.yamland creates or updates all elements in your project. It's idempotent: importing the same file twice doesn't create duplicates. Elements are matched by name and upserted. - Import as Project creates a brand-new project from a YAML file. Drop an
archyl.yamland get a fully populated project with one click.
This means you can start in the UI, export to YAML, commit to Git, and switch to the code-first workflow — or go the other way. There's no lock-in to either approach.
Smart Reference Resolution
One of the trickiest parts of the DSL is resolving element references in relationships, overlays, events, and API contracts. We built a resolver that handles this naturally:
- Short names work when unambiguous:
API Gatewayresolves directly if only one element has that name. - Dot-notation disambiguates:
Payment Service.API GatewayvsAnalytics.API Gateway. - Any depth works:
System.Container.Component.CodeElementfor deeply nested references.
The resolver indexes every element at every possible path depth, so you always use the shortest unambiguous reference. Exports use the same logic in reverse — producing the most readable references possible.
Validation Without Side Effects
Not sure if your YAML is valid? The /validate endpoint (and the "Validate" button in the import modal) parses and checks your file without touching the database:
- Schema version check
- Required field validation
- Duplicate name detection
- Type enumeration validation (container types, relationship types, etc.)
- Cross-reference resolution
Errors come back with precise paths (systems[2].containers[1].name) and clear messages. Wire it into a pre-commit hook or CI check and catch issues before they reach main.
Real-World Patterns
The Monorepo
# Root archyl.yaml
version: "1.0"
project:
name: "Our Platform"
include:
- services/payments/archyl.yaml
- services/users/archyl.yaml
- services/notifications/archyl.yaml
Each service maintains its own archyl.yaml defining its containers and components. The root file merges them, and cross-service relationships are defined at the root level. Technologies and environments are deduplicated automatically.
The Bootstrapper
Starting a new project? Create a archyl.yaml before writing any code. Define the systems and containers you plan to build. Use Archyl's "Import as Project" to generate the architecture instantly. As you build, the YAML evolves with the code.
The Audit Trail
Because the YAML is in Git, you get full history for free. git log archyl.yaml shows every architecture change, who made it, when, and the PR where it was discussed. Try getting that from a diagram tool.
The Documentation Generator
Export your architecture to YAML, then pipe it through any template engine to generate Markdown docs, Confluence pages, or internal wikis. The structured format makes it trivial to automate.
What's Next
This is version 1.0 of the DSL format. Here's what we're working on next:
Drift detection. Compare the YAML in your repo against the live model and highlight differences — elements added in the UI but not in the file, or vice versa.
PR preview comments. When a PR modifies archyl.yaml, a bot comments with a visual diff of what changed in the architecture.
Schema evolution. As we add new Archyl features, the DSL will grow. We'll maintain backward compatibility and provide migration tooling.
Try It Now
Architecture as Code is available today on all Archyl plans. If you already have a project:
- Go to the Architecture as Code page in your project
- Click Export to generate your
archyl.yaml - Commit it to your repository
- Add the official GitHub Action to your workflow and you're done
If you're starting fresh, create an archyl.yaml, use Import as Project, and you'll have a fully rendered C4 architecture in seconds.
Your architecture deserves the same rigor as your code. Version it, review it, automate it.
New to C4? Start with our Introduction to the C4 Model. Want AI to generate the initial architecture? See AI-Powered Architecture Discovery. Already using AI assistants? Connect them via our MCP Server.