Skip to content

Relationships

Relationships describe the connections, data flows and interactions within your model.

Relationships are usually defined with the -> operator:

model {
customer = actor 'Customer'
cloud = service 'Cloud'
customer -> cloud
}

Use <-> when both elements actively communicate with each other:

model {
frontend = component 'Frontend'
backend = component 'Backend'
frontend <-> backend 'Sync'
}

Bidirectional relationships render with arrows at both ends by default. Use them for mutual interactions, such as synchronized replication or protocols where both sides initiate meaningful communication. Relationship style can still override the rendered tail. For request-response calls where one side initiates the interaction, prefer ->.

Relationships may be nested

model {
service cloud {
component backend
component frontend
frontend -> backend
customer -> frontend
}
}

In nested relationships you can use it or this to refer parent:

model {
customer = actor {
// as a source
it -> frontend
// as a target
frontend -> this
}
}

Nested relationships may be “sourceless”, then the source is the parent element

model {
actor customer {
// same as customer -> frontend
-> frontend
}
service cloud {
component backend
component frontend {
// same as frontend -> backend
-> backend
}
}
}

Relationships can be “kinded”:

specification {
element system
// Define relationship kind
relationship async
relationship uses
}
model {
system1 = system 'System 1'
system2 = system 'System 2'
system3 = system 'System 3'
system1 -[async]-> system2
system1 -[async]<-> system3
// Or prefix with '.' to use the kind
system1 .uses system2
}

Use -[kind]<-> when a bidirectional relationship should also inherit a relationship kind.

This makes it possible to add richer semantics to the interactions between elements, for example, from a technology perspective (REST, gRPC, GraphQL, Sync/Async, etc.) or from a business perspective (delegation, informing, accountability, etc.).

You can define whichever relationship types best fit your context.

A relationship kind can also define tags and default properties — title, description, technology, notation and links — inherited by every relationship of that kind (a relationship may override any of the properties; tags are merged):

specification {
relationship async {
#tcp
title 'Asynchronous'
technology 'Kafka'
}
tag tcp
}
model {
// inherits tag #tcp, title 'Asynchronous' and technology 'Kafka'
system1 .async system2
// overrides the title, keeps the inherited tag and technology
system1 .async system3 'publishes events'
}

Relationships may have a title (and it’s better to have one):

model {
customer -> frontend 'opens in browser'
// or nested
customer -> frontend {
title 'opens in browser'
}
}
model {
customer -> frontend 'opens in browser' {
description 'Customer opens...'
}
// Or in a shorter way
customer -> frontend 'opens in browser' 'Customer opens...'
}

As with elements, you can use markdown in the description with triple quotes:

model {
customer -> frontend 'opens in browser' {
description '''
**Customer** opens the frontend in the browser
to interact with the system
| checks | |
|:--------- |:-- |
| check 1 | ✅ |
| check 2 | ⛔️ |
| check 3 | ✅ |
'''
}
}

Fenced code blocks are syntax highlighted when they specify a language. For diffs, use diff-<language> to highlight both the changes and the source language, for example diff-ts or diff-python.

model {
customer -> frontend 'opens in browser' {
technology 'HTTPS'
}
// Or in a shorter way
// order is [title] [description] [technology]
customer -> frontend 'opens in browser' 'Customer opens...' 'HTTPS'
}

Relationships can have tags:

model {
// inlined
frontend -> backend 'requests data' #graphql #team1
// or nested
customer -> frontend 'opens in browser' {
#graphql #team1
}
}

Relationships can have multiple links:

model {
customer -> frontend 'opens in browser' {
// 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
}
}

A relationship may have a navigateTo property, which links to a dynamic view.
This allows to “zoom-in” and see more details about this relationship.

model {
webApp -> backend.api {
title 'requests data for the dashboard'
navigateTo dashboard-request-flow
}
}

Same as element metadata:

model {
customer -> frontend 'opens in browser' {
metadata {
prop1 'value1'
prop2 '{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
}
}
}'
}
}
}