Pular para o conteúdo

Extending model

Este conteúdo não está disponível em sua língua ainda.

You can extend the model by creating new files and folders.
When LikeC4 source files are parsed, they are merged into a single architecture model.

You are free to organize the workspace as you want.

Assume we have the following workspace:

  • Directorycloud
    • service1.c4
    • service2.c4
  • Directoryexternals
    • amazon.c4
  • landscape.c4
  • specs.c4

This file defines the specification:

specification {
element actor {
style {
shape person
}
}
element system
element service
}

extend is a way to enrich the model and define nested elements in a separate file.

We don’t want to mess up the landscape.c4 file with the internals of the cloud.
In a separate file we extend cloud and define cloud.service1:

cloud/service1.c4
model {
// cloud is defined in landscape.c4
extend cloud {
// extend and define cloud.service1
service1 = service 'Service 1'
}
}

The element extension inherits the scope of the target (or, more accurately, the parent).
For example:

cloud/service2.c4
model {
// cloud is defined in landscape.c4
extend cloud {
// extend and define cloud.service2
service2 = service 'Some Service 2'
service2 -> service1 // ✅ service1 is known inside 'cloud'
}
}

You can extend element with additional tags, links and metadata:

model {
extend cloud {
// Add tags
#additional-tag, #another-tag
// Add metadata
metadata {
prop1 'value1'
}
// Add links
link ../src/index.ts#L1-L10
}
}

When extending elements with metadata, duplicate keys from both the original element and the extension are merged into arrays:

model {
component api {
metadata {
version '1.0.0'
tags 'backend'
regions 'us-east-1'
}
}
}
// In another file
model {
extend api {
metadata {
tags 'microservice' // Merges with existing 'backend'
regions ['eu-west-1'] // Merges with existing 'us-east-1'
owner 'platform-team' // New key
}
}
}
// Result:
{
version: '1.0.0',
tags: ['backend', 'microservice'], // Merged and kept as array
regions: ['us-east-1', 'eu-west-1'], // Merged and kept as array
owner: 'platform-team'
}

Merging behavior:

  • Duplicate values are automatically de-duplicated
  • If after de-duplication there’s only one unique value, it’s stored as a string (not an array)
  • Arrays from both sides are merged and de-duplicated
model {
component api {
metadata {
environment 'production'
tags ['backend', 'api']
}
}
}
model {
extend api {
metadata {
environment 'production' // Duplicate value
tags ['api', 'critical'] // 'api' is duplicate
}
}
}
// Result:
{
environment: 'production', // Single value (de-duplicated)
tags: ['backend', 'api', 'critical'] // Merged and de-duplicated
}

You can extend the same element multiple times across different files, and all metadata will be properly merged:

file1.c4
model {
component api {
metadata {
version '2.0.0'
tags 'backend'
}
}
}
// file2.c4
model {
extend api {
metadata {
tags 'rest'
owner 'team-a'
}
}
}
// file3.c4
model {
extend api {
metadata {
tags 'microservice'
regions ['us', 'eu']
}
}
}
// Result:
{
version: '2.0.0',
tags: ['backend', 'rest', 'microservice'],
owner: 'team-a',
regions: ['us', 'eu']
}

Similar to extending elements, you can extend relationships to add metadata, tags, and links from separate files.

Relations are uniquely identified by:

  • Source element
  • Target element
  • Relationship kind (if specified)
  • Title (if specified)
base.c4
specification {
element component
relationship sync
}
model {
component frontend
component api
// Untyped relation with title
frontend -> api "Makes requests"
// Typed relation with same title (different relation!)
frontend -[sync]-> api "Makes requests"
}
// extend-ops.c4
model {
// Extend the untyped relation
extend frontend -> api "Makes requests" {
metadata {
latency_p95 '150ms'
rate_limit '1000req/s'
}
}
// Extend the sync relation (different from above!)
extend frontend -[sync]-> api "Makes requests" {
metadata {
latency_p95 '80ms'
cache_enabled 'true'
}
}
}

Relationship extends follow the same metadata merging rules as element extends:

  • New keys are added
  • Duplicate keys with different values become arrays
  • Duplicate keys with the same value are de-duplicated
base.c4
model {
api -> database "Queries data" {
metadata {
protocol 'TCP'
}
}
}
// extend-1.c4
model {
extend api -> database "Queries data" {
metadata {
protocol 'SSL' // Creates array
timeout '5s' // New key
}
}
}
// extend-2.c4
model {
extend api -> database "Queries data" {
metadata {
protocol 'TLS' // Adds to array
retry_policy 'exponential' // New key
}
}
}
// Result:
{
protocol: ['TCP', 'SSL', 'TLS'],
timeout: '5s',
retry_policy: 'exponential'
}