# Model


The `model` describes architecture as a set of hierarchical elements and any relationships among them.

## Element

Element is a basic building block. It represents a logical part of the architecture.  
Any element must have a [`kind`](/dsl/specification#element-kind) and a `name` (_identifier_):

```likec4
specification {
  element actor
  element service
}

model {
  // element of kind 'actor' with the name 'customer'
  actor customer
  // element of kind 'service' named as 'cloud'
  service cloud

  // also possible with '=' and the name goes first
  cloud = service
}
```

Element name is required for references.  
It can contain letters, digits, hyphens and underscore, but can't start with a digit or contain `.`

| name        | valid    |
| :---------  | :-- |
| api         | ✅  |
| Api2        | ✅  |
| \_api       | ✅  |
| \__Api-1    | ✅  |
| 1api        | ⛔️  |
| a.pi        | ⛔️  |


## Element Properties

### Title

```likec4 'SaaS' copy
specification {
  element softwareSystem
}
model {
  // Title can be inlined 
  saas = softwareSystem 'SaaS'
  
  // or nested
  saas = softwareSystem {
    title 'SaaS'

    // You can use `:` (optional)
    title: 'SaaS'
  }

  // If title is not specified, name will be used by default
  saas = softwareSystem
}
```

:::note
You can use single or double quotes:
```likec4
model {
  service cloud 'Cloud Service' 
  // Or
  service cloud "Cloud Service"
}
```
If you need quotes inside, escape with backslash:
```likec4
model {
  service cloud 'Cloud\'s Service' 
  service cloud "Cloud\"s Service"
}
```
:::

### Description

```likec4  'Provides services to customers' copy
model {
  // Can be inlined 
  saas = softwareSystem 'SaaS' 'Provides services to customers'
  
  // or nested
  saas = softwareSystem {
    title 'SaaS'
    description 'Provides services to customers'
  }
}
```

Element may have a short `summary` (optional, falls back to `description`):

```likec4 copy
model {
  saas = softwareSystem {
    title 'SaaS'
    summary 'Provides services to customers'
    description '
      Detailed description
      ...
    '
  }
}
```

If `summary` is provided, it will be shown on the diagram, and `description` in the details dialog.  
If you don't provide `description`, summary will be used.

For inlined definition:
```likec4 copy
model {
  // [title] [summary]
  saas = softwareSystem 'SaaS' 'Provides services to customers' {
    description '
      Detailed description
      ...
    '
  }
}
```

### Technology

```likec4 copy
model {
  api = service {
    technology 'REST'
  }

  // Structurizr DSL style:
  // <name> = softwareSystem [title] [summary] [technology]
  saas = softwareSystem 'SaaS' 'Provides services to customers' 'SaaS'  
}
```

:::tip
You can define element properties in [specification](/dsl/specification#element-kind), if it is common for all of the kind:

```likec4
specification {
  element mobileApp {
    title 'Mobile App'
    description 'Universal mobile application'
    technology 'React Native'
  }
}
```

This allows to define properties once and reuse them across the model.  
Properties from the element definition override the ones from the specification.
:::

### Tags

Element [tags](/dsl/specification/#tag) are defined in a nested block and must come first, before any properties:

```likec4 copy
model {
  appV1 = application 'App v1' {
    #deprecated
    description 'Old version of the application'
  }

  // multiple tags
  appV2 = application {
    #next, #serverless
    #team2
    title 'App v2'
  }

  appV3 = application {        
    title 'App v3'
    #team3 // ⛔️ Error: tags must be defined first
  }  
}
```

:::tip

You can add tags in the [specification](/dsl/specification/#tag), if it is common for all of the kind:

```likec4
specification {
  element lambda {
    #serverless
  }
}
```
:::

### Links

Element may have multiple links:

```likec4 copy
model {
  bastion = application 'Bastion' {
    // External link
    link https://any-external-link.com

    // With label
    link https://github.com/likec4/likec4 'Repository'

    // or any URI
    link ssh://bastion.internal 'SSH'

    // or relative link to navigate to sources
    link ../src/index.ts#L1-L10
  }
}
```

### Metadata

Element metadata is a set of key-value pairs, defined in a nested block:

```likec4 copy
model {
  app = application 'App' {
    metadata {
      prop1 'value1'
      prop2 '
        apiVersion: apps/v1
        kind: StatefulSet
        metadata:
          name: app-statefulset
        spec: {}        
      '
      prop3 '{
        "$schema": "https://json-schema.org/draft/2020-12/schema",
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "age": {
            "type": "integer"
          }
        }
      }'
    }
  }
}
```

Only string values are allowed, but you can use JSON or YAML format for complex data.

### Array Values

You can also use arrays for metadata values using array literal syntax:

```likec4 copy
model {
  app = application 'App' {
    metadata {
      tags ['frontend', 'react', 'typescript']
      environments ['dev', 'staging', 'prod']
      version '2.1.0'
    }
  }
}
```

Mixed single and array values are supported in the same metadata block:

```likec4 copy
model {
  api = service 'API Gateway' {
    metadata {
      version '3.2.1'
      maintainer 'Platform Team'
      tags ['backend', 'gateway', 'microservice']
      regions ['us-east-1', 'eu-west-1']
      critical true
    }
  }
}
```

Here are more examples showing various mixed metadata patterns:

```likec4 copy
model {
  // E-commerce application with mixed metadata types
  frontend = application 'Frontend App' {
    metadata {
      framework 'React'
      version '18.2.0'
      features ['shopping-cart', 'user-auth', 'payment', 'search']
      deployment_targets ['staging', 'production']
      team_lead 'Alice Johnson'
      developers ['Bob Smith', 'Carol Davis', 'David Wilson']
      release_cycle 'weekly'
      supported_browsers ['Chrome', 'Firefox', 'Safari', 'Edge']
      accessibility_level 'WCAG 2.1 AA'
      has_mobile_app true
    }
  }

  // Database service with operational metadata
  database = service 'PostgreSQL Cluster' {
    metadata {
      engine 'PostgreSQL'
      version '15.3'
      instances ['primary', 'replica-1', 'replica-2']
      backup_schedule 'daily'
      backup_retention_days '30'
      monitoring_endpoints ['metrics', 'logs', 'traces']
      alert_channels ['slack', 'email', 'pagerduty']
      maintenance_window 'Sunday 2-4 AM UTC'
      data_classification 'sensitive'
      encryption_at_rest true
    }
  }

  // Microservice with complex deployment metadata
  payment = service 'Payment Service' {
    metadata {
      language 'Go'
      version '2.1.4'
      port '8080'
      health_check_path '/health'
      dependencies ['database', 'redis', 'external-payment-api']
      environments ['dev', 'test', 'stage', 'prod']
      scaling_policy 'auto'
      min_replicas '2'
      max_replicas '10'
      circuit_breaker_enabled true
      rate_limits ['1000/minute', '100/second']
      compliance_standards ['PCI-DSS', 'SOC2']
    }
  }
}
```

### Metadata Properties Behavior

**Alphabetic Ordering**: Metadata properties are automatically sorted alphabetically when displayed in element details, regardless of the order they are defined in the DSL. This ensures consistent presentation across all elements.

**Property Duplications**: When the same property name is defined multiple times within a metadata block, all values are collected into an array, preserving their order of definition:

```likec4 copy
model {
  service = component 'Payment Service' {
    metadata {
      version '1.0.0'               // First value
      version '2.0.0'               // Second value  
      // Result: version: ['1.0.0', '2.0.0']
      
      owner ['team-a', 'team-b']    // First: array values
      owner 'team-c'                // Second: single value
      // Result: owner: ['team-a', 'team-b', 'team-c']
      
      tags 'primary'                // First: single value
      tags ['backend', 'critical']  // Second: array values  
      // Result: tags: ['primary', 'backend', 'critical']
      
      ports ['8080', '9090']        // First: array values
      ports ['3000', '4000']        // Second: array values
      // Result: ports: ['8080', '9090', '3000', '4000']
    }
  }
}
```

This behavior applies to **all duplicate keys**. 

All metadata properties are displayed alphabetically, regardless of definition order.

```likec4 copy
model {
  api = service 'API Gateway' {
    metadata {
      version '3.2.1'
      maintainer 'Platform Team'
      tags ['backend', 'gateway', 'microservice']
      regions ['us-east-1', 'eu-west-1']
      critical true
    }
  }
}
```

Here are more examples showing various mixed metadata patterns:

```likec4 copy
model {
  // E-commerce application with mixed metadata types
  frontend = application 'Frontend App' {
    metadata {
      framework 'React'
      version '18.2.0'
      features ['shopping-cart', 'user-auth', 'payment', 'search']
      deployment_targets ['staging', 'production']
      team_lead 'Alice Johnson'
      developers ['Bob Smith', 'Carol Davis', 'David Wilson']
      release_cycle 'weekly'
      supported_browsers ['Chrome', 'Firefox', 'Safari', 'Edge']
      accessibility_level 'WCAG 2.1 AA'
      has_mobile_app true
    }
  }

  // Database service with operational metadata
  database = service 'PostgreSQL Cluster' {
    metadata {
      engine 'PostgreSQL'
      version '15.3'
      instances ['primary', 'replica-1', 'replica-2']
      backup_schedule 'daily'
      backup_retention_days '30'
      monitoring_endpoints ['metrics', 'logs', 'traces']
      alert_channels ['slack', 'email', 'pagerduty']
      maintenance_window 'Sunday 2-4 AM UTC'
      data_classification 'sensitive'
      encryption_at_rest true
    }
  }

  // Microservice with complex deployment metadata
  payment = service 'Payment Service' {
    metadata {
      language 'Go'
      version '2.1.4'
      port '8080'
      health_check_path '/health'
      dependencies ['database', 'redis', 'external-payment-api']
      environments ['dev', 'test', 'stage', 'prod']
      scaling_policy 'auto'
      min_replicas '2'
      max_replicas '10'
      circuit_breaker_enabled true
      rate_limits ['1000/minute', '100/second']
      compliance_standards ['PCI-DSS', 'SOC2']
    }
  }
}
```

```likec4 copy
model {
  api = service 'API Gateway' {
    metadata {
      version '3.2.1'
      maintainer 'Platform Team'
      tags ['backend', 'gateway', 'microservice']
      regions ['us-east-1', 'eu-west-1']
      critical true
    }
  }
}
```

```likec4 copy
model {
  api = service 'API Gateway' {
    metadata {
      version '3.2.1'
      maintainer 'Platform Team'
      tags ['backend', 'gateway', 'microservice']
      regions ['us-east-1', 'eu-west-1']
      critical true
    }
  }
}
```

## Using Markdown

You can use markdown in `description` (and `summary`) with triple quotes: 

```likec4 copy
model {
  mobile = application {     
    title 'Mobile Application'
    description '''
      ### Multi-platform application
      
      [React Native](https://reactnative.dev)
    '''
  }

  web = application {
    description """
      ### Web Application
      
      > Provides services to customers through
      > the web interface.

      | checks     |     |
      | :--------- | :-- |
      | check 1    | ✅  |
      | check 2    | ⛔️  |
      | check 3    | ✅  |
    """
  }  
}
```

## Structuring Model

Any element is a container and can contain other elements.  
This way you define the structure and internals of the element.

```likec4 filename="nested-elements.c4"
model {
  // service1 has backend and frontend
  service service1 {
    component backend {
      // backend has api
      component api
    }
    component frontend
  }

  // or use '='
  service2 = service {
    backend = component {
      api = component
    }
    frontend = component
  }
}
```

Nested elements are _"namespaced"_, the parent name is used as a prefix.  
So, the model above has the elements with these fully qualified names:

- `service1`
- `service1.backend`
- `service1.backend.api`
- `service1.frontend`

and:

- `service2`
- `service2.backend`
- `service2.backend.api`
- `service2.frontend`

:::caution
It is not possible to have elements with the same name on the same hierarchy level.  
It is explained in detail in [references](/dsl/references).

```likec4 filename="nested-elements.c4"
model {

  service service1 'Service 1' {
    component backend

    component backend // ⛔️ Error: 'service1.backend' already defined
  }

  service service2 'Service 2' {
    component backend // ✅ This is OK - 'service2.backend'

    component legacy {
      component backend // ✅ This is OK - 'service2.legacy.backend'
    }
  }

  component backend // ✅ This is OK - 'backend'
}
```
:::