Skip to content

Model

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

An element is a basic building block. It represents a logical part of the architecture.
Any element must have a kind and a name (identifier):

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
}

An element name is required for references. It can contain letters, digits, hyphens, and underscores, but cannot start with a digit or contain .

namevalid
api
Api2
_api
__Api-1
1api⛔️
a.pi⛔️
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
}
model {
// Can be inlined
saas = softwareSystem 'SaaS' 'Provides services to customers'
// or nested
saas = softwareSystem {
title 'SaaS'
description 'Provides services to customers'
}
}

An element may have a short summary (optional; falls back to description):

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 the description will be shown in the details dialog.
If you don’t provide description, summary will be used.

For inlined definition:

model {
// [title] [summary]
saas = softwareSystem 'SaaS' 'Provides services to customers' {
description '
Detailed description
...
'
}
}
model {
api = service {
technology 'REST'
}
// Structurizr DSL style:
// <name> = softwareSystem [title] [summary] [technology]
saas = softwareSystem 'SaaS' 'Provides services to customers' 'SaaS'
}

Element tags are defined in a nested block and must come first, before any other properties:

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

An element may have multiple links:

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

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

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.

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

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:

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:

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']
}
}
}

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

Property Duplication: When the same property name is defined multiple times, all values are collected into an array, preserving their definition order:

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.

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:

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']
}
}
}
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
}
}
}
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
}
}
}

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

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 | ✅ |
"""
}
}

Any element can act as a container and include other elements.
This way you define the structure and internals of the element.

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