This post continues from Part 25. An architecture model maintained by a single person has no merge problem. As soon as multiple teams work on the same repository, that changes. Bausteinsicht comes with good preconditions for this — but you need to know where the limits are.
What merges well in JSONC
JSONC is a text format. Git merges text files line by line. That means:
Merges cleanly:
Adding new elements in
model— as long as the elements have different IDs, these are separate lines with no overlapAdding new views in
views— same principleAdding new tags in
specification.tags
Conflict-prone:
Modifying the same element simultaneously (title, description, technology)
Changing the order of elements — Git sees this as a deletion + insertion
specification.elementsandspecification.relationships— these areas are changed less often, but when they are, often by multiple people at once
draw.io XML is harder: The .drawio file contains XML with IDs and positions. Merge conflicts there are harder to resolve than JSONC. Rule of thumb: the JSONC model is the source of truth, the draw.io file is regenerable via sync.
Ownership Conventions
In a larger system, each team owns a section of the model it maintains. Conventions help to structurally avoid conflicts rather than just repairing them.
Recommendation: Element IDs with team prefix:
{
"model": {
"backend.auth-service": { "kind": "service", "title": "Auth Service" },
"backend.user-service": { "kind": "service", "title": "User Service" },
"frontend.shop-ui": { "kind": "frontend", "title": "Shop UI" },
"infra.postgres": { "kind": "database", "title": "PostgreSQL" }
}
}The backend team changes backend., the frontend team changes frontend..
Relationships between teams — backend.auth-service → infra.postgres — fall in the consumer’s sphere of influence (whoever initiates the relationship defines it).
CODEOWNERS file: In GitHub this can be enforced with CODEOWNERS:
# CODEOWNERS
architecture/ @architecture-team # every change requires reviewOr more granularly (if the model is split up):
architecture/specification/ @all-teams
architecture/model/backend/ @backend-team
architecture/model/frontend/ @frontend-team| Bausteinsicht stores everything in a single JSONC file. If teams truly want to work independently, the Workspace feature (Part 16) is the solution — separate models with explicit cross-references. |
Resolving Merge Conflicts
A typical JSONC conflict looks like this:
{
"model": {
<<<<<<< HEAD
"backend.auth-service": {
"kind": "service",
"title": "Authentication Service",
"technology": "Go"
},
=======
"backend.auth-service": {
"kind": "service",
"title": "Auth Service",
"technology": "Go 1.22"
},
>>>>>>> feature/update-auth
}
}Strategy:
Open the conflict in a JSON editor (not a plain text merge)
Make the content decision — which title, which technology version?
Merge manually, then run
bausteinsicht validateIf the draw.io file also has a conflict: discard it and rerun
bausteinsicht sync— the JSONC side is the source of truth
Run bausteinsicht validate --format json after every merge. Exit code 1 on errors prevents a broken model from landing in main. |
Architecture Review in the Pull Request
Making architecture changes visible in PRs is the real advantage of Architecture-as-Code.
Workflow:
Developer opens a feature branch and modifies the model
CI runs
bausteinsicht validateandbausteinsicht diff(→ Part 24)Diff output appears as a PR comment: which elements were added, changed, removed
Reviewer sees the architecture change directly in the PR without a local installation
What a good architecture PR contains:
Only model changes that belong to the feature — no refactoring in the same PR
validateresult is greenA description that explains why the model was changed this way, not just what
When does a change need a review?
| Change | Review needed? |
|---|---|
New leaf element in an existing system | Optional — team-internal review is sufficient |
New external dependency | Yes — affects other teams |
Change in | Yes — changes the schema for everyone |
Adding or removing a view | Optional — does not affect logic |
Deleting an element referenced by others | Yes — |
A Realistic Team Workflow
git checkout -b feature/add-notification-service
# Modify model: add notification-service to model
# Relationships: shop-api → notification-service, notification-service → sendgrid
bausteinsicht validate # check locally
bausteinsicht sync # update draw.io
git add architecture/
git commit -m "arch: add notification service"
git push && gh pr createCI validates, diff shows:
- ` Element `notification-service` (kind: service)
- ` Element sendgrid (kind: external)
- ` Relationship `shop-api` → `notification-service`
- ` Relationship notification-service → sendgrid
The reviewer sees exactly what changed architecturally — without having to open the draw.io file.
Example Model
The example for this part (team ownership via tags, separate team views) is available at teil_26.jsonc.
Here is what the result looks like in draw.io (bausteinsicht sync):
You can find the draw.io file here: teil_26.drawio
Generated PNG files via bausteinsicht export --image-format png:



Generated PlantUML diagrams via bausteinsicht export-diagram:
Up Next: Custom Notations
As soon as teams bring their own vocabulary — AUTOSAR components, hardware elements, domain-specific concepts — the standard C4 notation is no longer sufficient. The next part covers how to define custom element types with custom shapes in draw.io.
Official documentation: User Manual · Tutorial on doctoolchain.org