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 overlap

  • Adding new views in views — same principle

  • Adding 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.elements and specification.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-serviceinfra.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 review

Or 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:

  1. Open the conflict in a JSON editor (not a plain text merge)

  2. Make the content decision — which title, which technology version?

  3. Merge manually, then run bausteinsicht validate

  4. If 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:

  1. Developer opens a feature branch and modifies the model

  2. CI runs bausteinsicht validate and bausteinsicht diff (→ Part 24)

  3. Diff output appears as a PR comment: which elements were added, changed, removed

  4. 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

  • validate result is green

  • A description that explains why the model was changed this way, not just what

When does a change need a review?

ChangeReview needed?

New leaf element in an existing system

Optional — team-internal review is sufficient

New external dependency

Yes — affects other teams

Change in specification (new element types)

Yes — changes the schema for everyone

Adding or removing a view

Optional — does not affect logic

Deleting an element referenced by others

Yes — validate will flag it anyway

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 create

CI validates, diff shows: - ` Element `notification-service` (kind: service) - ` Element sendgrid (kind: external) - ` Relationship `shop-api` → `notification-service` - ` Relationship notification-servicesendgrid

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:

context
team-payment
team-shop

Generated PlantUML diagrams via bausteinsicht export-diagram:

Diagram
Diagram
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