Skip to content

Model

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

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
}

Element name is required for references.
It can contain letters, digits, hyphens and underscore, but can’t 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'
}
}

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

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

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 is a container and can contain 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