Relationship Guide
Choose syntax
Use an arrow to describe direction and line style:
| Syntax | Meaning |
|---|---|
a > b | Shorthand forward edge |
a -> b | Forward edge |
a <- b | Reverse edge |
a <-> b | Bidirectional edge |
a -- b | Undirected edge |
a -.-> b | Dotted forward edge |
Direction affects semantics. The direction document directive affects layout
only.
Add a machine-readable kind
Place a kind inside square brackets:
api -[invokes]-> worker
worker -[writes]-> database
database -[replicates]-> replicaArchLex preserves the kind on CloudEdge. Provider rules use it to validate
source, target, and placement.
Core recognizes these kinds, grouped by area:
| Area | Kinds |
|---|---|
| Connectivity | connects, routes, proxies, exposes |
| Dependency | depends-on, attaches |
| Data | reads, writes, caches, encrypts, decrypts, streams, stores, backs-up, restores, archives |
| Events | publishes, subscribes, invokes, triggers, schedules, notifies |
| Operations | monitors, logs, traces, alerts |
| Processing | processes, transforms, analyzes, transcodes, packages |
| Delivery | orchestrates, builds, deploys, provisions |
| Governance | assumes-role, protects, governs, catalogs, authenticates, authorizes, audits, scans, trusts |
| Reliability | fails-over-to |
| Lifecycle | replicates, migrates, discovers |
The area of each kind is part of the language metadata
(RelationshipDefinition.area) and is exposed through the catalog API.
Provider validation
Mixed diagrams validate resources by their provider identity, including qualified
resources such as cloudflare.workers, aws.lambda, gcp.cloud-run, and
k8s.deployment. Each provider receives its own nodes, edges whose endpoints
both belong to that provider, and the matching containment context. Resource
names shared by providers do not activate another provider’s rules. Core recognizes
relationship kinds declared by any registered provider, including Kubernetes
targets in a diagram whose default provider is Cloudflare.
Cross-provider edges remain in the rendered graph. Provider-local relationship
constraints do not apply to those edges; core syntax and structural diagnostics
still apply. off skips provider validation for every provider.
Providers declare which kinds they understand and which services may take part
in them. AWS, Google Cloud, and Kubernetes each ship relationship definitions
with allowed sources and targets; a typed edge that violates them produces a
provider diagnostic (AWS-RELATIONSHIP-INVALID-ENDPOINT-001,
GCP-RELATIONSHIP-INVALID-ENDPOINT-001,
K8S-RELATIONSHIP-INVALID-ENDPOINT-001). In strict mode these warnings
become errors; off skips them. Cloudflare does not declare endpoint pairs.
It reports CLOUDFLARE-CONTAINMENT-001 when a recognized Cloudflare node is
nested in a native scope.
For example, AWS declares that orchestrates flows from Step Functions to
Lambda, ECS, Glue, or SageMaker, so dynamodb -[orchestrates]-> lambda is
flagged while step-functions -[orchestrates]-> lambda is accepted.
Kubernetes declares provider-specific targets (Service to workload), routes
(Ingress to Service), mounts (workload to storage/configuration), binds
(PersistentVolumeClaim to PersistentVolume), scales
(HorizontalPodAutoscaler to workload), and schedules-on (Pod to Node)
relationships.
Use getCatalog() to read the current core list and each provider’s declared
relationships.
Add display text
Use pipe syntax when readers need protocol or route detail:
api -[writes]->|PostgreSQL over TLS| databaseThe kind remains writes. The renderer displays PostgreSQL over TLS. Labels
do not change provider semantics.
Build chains
gateway -[invokes]-> worker -[writes]-> databaseThe chain creates two edges. Each operator owns the relationship that follows it. Name repeated resources when one diagram needs several instances of a kind.
Provider examples
AWS
provider aws
gateway: api-gateway
worker: lambda
queue: sqs
gateway -[invokes]-> worker
worker -[publishes]-> queueGoogle Cloud
provider gcp
events: pubsub
worker: cloud-functions
warehouse: bigquery
events -[triggers]-> worker
worker -[writes]-> warehouseKubernetes
provider k8s
cluster production {
namespace web {
edge: ingress
api_service: service
api: deployment
edge -[routes]-> api_service
api_service -[targets]-> api
}
}Kubernetes enforces the declared routes (Ingress to Service) and targets
(Service to workload) constraints. Untyped edges are still checked
topologically: a Service connected to a workload satisfies the target check
even without a targets kind.
Cloudflare
Cloudflare reuses the core kinds above. It does not add a provider-specific
kind, and it does not validate typed-edge endpoints. listRelationships() is
empty so catalog discovery does not invent source/target pairs. Put reader
detail in a display label.
| Intent | Kind | Why |
|---|---|---|
| DNS name selects an entry | untyped ->|DNS record selects entry point| | Not an HTTP hop. Do not invent resolves. |
| HTTPS origin request | proxies | Request forwarding, including Tunnel request flow. |
| Tunnel establishment | connects | Origin connector to managed Tunnel. Opposite direction from request flow. |
| WAF or similar control | protects | Capability association, not a mandatory hop. |
| Access policy | authorizes | Capability association, not a mandatory hop. |
| Response cache | caches | Eligible responses, not a separate appliance hop. |
| Worker reads object storage | reads | Data dependency, such as Workers to R2. |
| Origin preference or fallback | routes | Steering intent. Do not use fails-over-to; the diagram does not prove health. |
provider cloudflare
account production {
domain: dns["app.example.com"]
entry: workers["Application entry"]
protection: waf["WAF policy"]
objects: r2["Application objects"]
domain ->|DNS record selects entry point| entry
protection -[protects]-> entry
entry -[reads]-> objects
}Unknown kinds
ArchLex keeps custom kinds so you can express domain-specific relationships. Provider validation may emit an informational diagnostic when it cannot evaluate the kind. The edge still renders.
Use a known kind when you want current provider rules to understand intent. Use a display label when you only need reader-facing detail.