API ReferenceEdges & Protocols

Edges & Protocols

Edges represent the transport-layer connections between nodes. Understanding edge direction is the single most important concept for building correct cloud-arch diagrams.


The Edge Direction Rule

⚠️

connect(A, B) means A opens the TCP connection to B.

The arrow direction answers the question: who dials whom? It does NOT indicate the direction of data flow. Once a TCP connection is established, data flows in both directions. Responses travel back along the same edge in reverse animation — you never need a duplicate edge for responses.

Think of it as asking: which process runs connect() or dial() at the OS socket level?

  • Spark reads Postgres via JDBC → Spark calls connect()connect('spark', 'pg')
  • A Kafka consumer reads from a broker → Consumer calls connect()connect('flink', 'kafka')
  • Airflow submits a Spark job via the K8s API → Airflow calls connect()connect('airflow', 'spark')

Correct vs wrong examples

ScenarioCorrectWrongReason
Spark reads Postgres via JDBCconnect('spark', 'pg')connect('pg', 'spark')Spark opens the JDBC socket to Postgres
Airflow submits Spark jobconnect('airflow', 'spark')connect('spark', 'airflow')Airflow calls the K8s/Spark API
Debezium reads WALconnect('debezium', 'pg-primary')connect('pg-primary', 'debezium')Debezium opens the replication slot
Kafka consumerconnect('flink', 'kafka')connect('kafka', 'flink')Consumer connects to the broker
Trino queries Icebergconnect('trino', 'iceberg')connect('iceberg', 'trino')Trino calls the Iceberg REST catalog API

Responses do not need new edges

The FlowBuilder handles reverse animation automatically:

// ONE edge in the topology
topology.connect('client', 'api', { protocol: 'http', label: 'REST' });
 
// Animation: request goes forward, response goes backward on the SAME edge
flow
  .from('client').to('api')   // forward
  .showMessage('[GET] /data')
  .from('api').to('client')   // REVERSE — no extra edge needed
  .showMessage('[200 OK] Here is your data');

Edge types

The type property in ConnectionOptions controls which React component renders the edge.

TypeComponentDescription
floatingAnimatedFloatingEdgeDefault. Smooth animated dashes. Works correctly with nodes inside groups.
animatedAnimatedEdgeSimple animated dashes. Use for basic diagrams without group nesting.
pulsePulseEdgePulsing glow effect. Recommended for Kafka, RabbitMQ, and event-stream connections.
topology.connect('producer', 'kafka', { type: 'pulse',    protocol: 'kafka' });
topology.connect('api',      'db',    { type: 'floating', protocol: 'postgresql' });

Protocol color map

The protocol property controls the edge color. Use it to make connection types visually distinguishable at a glance.

ProtocolColorTypical use
httpBlueREST APIs, HTTP webhooks
httpsBlueTLS-encrypted HTTP
grpcIndigogRPC service calls
postgresqlDark bluePostgreSQL / JDBC
mysqlOrangeMySQL
redisRedRedis commands
kafkaOrange-yellowKafka produce / consume
rabbitmqOrangeAMQP messages
tcpGrayRaw TCP (unspecified protocol)
udpLight grayUDP datagrams
websocketTealWebSocket connections
amqpOrangeGeneric AMQP

If no protocol is specified, the edge renders in the default gray.


Full edge options reference

topology.connect(source: string, target: string, options?: {
  label?: string;          // Text shown at the midpoint of the edge
  protocol?: string;       // Controls edge color
  type?: 'floating' | 'animated' | 'pulse';  // Edge component
  layer?: string;          // Visibility layer
  animated?: boolean;      // Enable/disable dash animation (default: true)
  bidirectional?: boolean; // Render arrowheads on both ends (default: false)
})

Common mistakes

Mistake 1: Adding reverse edges for responses

// WRONG — creates two visible edges on the canvas
topology.connect('client', 'api', { protocol: 'http' });
topology.connect('api', 'client', { protocol: 'http' }); // redundant
 
// CORRECT — one edge, FlowBuilder handles reverse automatically
topology.connect('client', 'api', { protocol: 'http' });

Mistake 2: Edge bypasses a proxy

// WRONG — client bypasses the circuit breaker in the response path
topology.connect('client', 'cb',      { protocol: 'http' });
topology.connect('cb',     'service', { protocol: 'http' });
topology.connect('service', 'client', { protocol: 'http' }); // bypasses cb!
 
// CORRECT — responses go back through the circuit breaker
topology.connect('client', 'cb',      { protocol: 'http' });
topology.connect('cb',     'service', { protocol: 'http' });
// Response path: service → cb (reverse) → client (reverse)

Mistake 3: Wrong initiator direction

// WRONG — a Kafka broker does not dial consumers
topology.connect('kafka', 'flink', { protocol: 'kafka' });
 
// CORRECT — Flink consumers dial the Kafka broker
topology.connect('flink', 'kafka', { protocol: 'kafka' });