Skip to content

Architecture Overview

ChainGraph is a source-available, flow-based programming framework that empowers developers to visually design, execute, and manage complex computational graphs. It combines a type-safe node-and-port system with a robust distributed execution engine, providing real-time synchronization through WebSockets.

Core Concepts

ChainGraph is built on four foundational concepts:

1. Nodes

Nodes are discrete computational units that perform specific tasks. Each node:

  • Extends BaseNodeCompositional abstract class
  • Implements an async execute(context: ExecutionContext) method
  • Has input and output ports for data flow
  • Emits events during execution
  • Supports batch port updates for performance

Example node structure:

typescript
@Node({
  title: 'Example Node',
  category: 'utilities'
})
class ExampleNode extends BaseNode {
  @Input()
  @String()
  input: string = ''

  @Output()
  @Number()
  output: number = 0

  async execute(context: ExecutionContext): Promise<NodeExecutionResult> {
    this.output = this.input.length
    return {}
  }
}

2. Ports

Ports are typed connection points that define how data flows between nodes. The port system supports:

Primitive Types:

  • StringPort - Text data
  • NumberPort - Numeric values
  • BooleanPort - True/false values

Complex Types:

  • ObjectPort - Structured objects with child ports
  • ArrayPort - Collections of items
  • StreamPort - Asynchronous data streams
  • EnumPort - Restricted value sets
  • AnyPort - Dynamic typing

Each port has:

  • Configuration (IPortConfig) defining constraints
  • Runtime validation via Zod schemas
  • Connection tracking
  • Conditional visibility rules

3. Flows

Flows are directed acyclic graphs (DAGs) composed of nodes and edges. A flow:

  • Contains multiple nodes connected through ports
  • Manages event propagation
  • Supports serialization and cloning
  • Provides validation and debugging
  • Can contain parent-child node relationships

4. Execution Engine

The Execution Engine orchestrates flow execution:

  • Resolves node dependencies automatically
  • Supports parallel execution where possible
  • Handles child execution spawning
  • Tracks execution depth to prevent infinite recursion
  • Provides debugging capabilities (breakpoints, step-over)
  • Emits real-time events for monitoring

System Architecture

┌────────────────────────────────────────────────────────────┐
│                    Frontend (React + Vite)                 │
│  ┌─────────────┐  ┌──────────────┐  ┌──────────────┐       │
│  │   XYFlow    │  │   Effector   │  │  tRPC Client │       │
│  │   Canvas    │  │  State Mgmt  │  │  + WebSocket │       │
│  └─────────────┘  └──────────────┘  └──────────────┘       │
└────────────────────────────┬───────────────────────────────┘
                             │ WebSocket + tRPC
┌────────────────────────────┴───────────────────────────────┐
│                  Backend (Node.js + tRPC)                  │
│  ┌──────────────┐  ┌─────────────┐  ┌──────────────┐       │
│  │ tRPC Router  │  │ Flow Store  │  │ Execution    │       │
│  │ (API Layer)  │  │ (Postgres)  │  │ Service      │       │
│  └──────────────┘  └─────────────┘  └──────────────┘       │
└────────────────────────────┬───────────────────────────────┘

┌────────────────────────────┴───────────────────────────────┐
│            Distributed Execution (DBOS)                    │
│  ┌──────────────┐  ┌─────────────┐  ┌──────────────┐       │
│  │     DBOS     │  │  PostgreSQL │  │  Execution   │       │
│  │  Workflows   │  │  State DB   │  │  Workers     │       │
│  └──────────────┘  └─────────────┘  └──────────────┘       │
└────────────────────────────────────────────────────────────┘

Project Structure

Core Packages

packages/chaingraph-types

The foundation package providing:

  • Node system (BaseNodeCompositional)
  • Port implementations and interfaces
  • Flow management classes
  • Execution engine
  • Decorator system
  • Type definitions and utilities

See API Reference for details.

packages/chaingraph-nodes

Pre-built node implementations:

  • AI nodes (Anthropic Claude, Google Gemini)
  • Data transformation nodes
  • Flow control nodes
  • Utility nodes
  • Math and logic nodes

Over 114 ready-to-use nodes organized by category.

packages/chaingraph-trpc

Type-safe API layer providing:

  • Flow CRUD operations
  • Node management procedures
  • Execution control endpoints
  • Real-time subscriptions via WebSockets
  • Debugging utilities

packages/chaingraph-executor

Backend execution engine with:

  • Task queue (in-memory and DBOS-based)
  • Execution service
  • Recovery service for fault tolerance
  • DBOS durable workflows for distributed execution
  • Metrics and monitoring

packages/chaingraph-codegen

Code generation utilities for creating nodes from schemas.

Applications

apps/chaingraph-backend

Node.js backend server that:

  • Hosts the tRPC API
  • Manages WebSocket connections
  • Stores flows and execution state
  • Coordinates execution workers

apps/chaingraph-frontend

React + Vite frontend featuring:

  • Visual flow editor (XYFlow-based)
  • Effector-based state management
  • Real-time updates
  • Node property inspector
  • Execution visualization

apps/chaingraph-execution-api

API service for distributed execution management.

apps/chaingraph-execution-worker

Worker processes for executing flows in a distributed system.

Key Architectural Patterns

1. Decorator-Based Configuration

Nodes use TypeScript decorators for metadata definition:

typescript
@Node({
  title: 'My Node',
  category: 'utilities'
})
class MyNode extends BaseNode {
  @Input()
  @String({ defaultValue: 'hello' })
  input: string = 'hello'
}

Benefits:

  • Co-located logic and configuration
  • Compile-time and runtime type safety
  • Automatic UI generation
  • Self-describing nodes

2. Compositional Architecture

BaseNodeCompositional delegates responsibilities to specialized components:

  • UnifiedPortStorage - Centralized port state
  • VirtualPortManager - Port hierarchy management
  • OperationExecutor - Schema and port operations
  • NodeEventManager - Event pub/sub
  • NodeUIManager - UI state
  • SystemPortManager - Flow control ports

This provides:

  • Single Responsibility Principle
  • Testable components
  • Extensibility without modifying base class

3. Event-Driven Synchronization

Node Port Updated

Node.emit(PortUpdateEvent)

Flow.handleNodeEvent()

Flow.emitEvent(FlowEvent)

WebSocket → Frontend

UI Updates

Event types:

  • NodeEvents: Status changes, port updates, connections
  • FlowEvents: Node/edge additions, port updates
  • ExecutionEvents: Start, completion, failures

4. Distributed Execution

For scalability, ChainGraph supports distributed execution using DBOS:

Client → PostgreSQL (Source of Truth)

DBOS Durable Workflows (Orchestration)

Execution Workers (Horizontally Scalable)

Automatic Recovery (DBOS Built-in)

Features:

  • Transactional guarantees - DBOS + PostgreSQL ensure consistency
  • Fault tolerance - Automatic recovery of interrupted workflows
  • Horizontal scaling - Add more worker instances
  • Durable execution - Workflows survive process restarts

Data Flow: End-to-End

Creating and Executing a Flow

  1. User creates flow in UI

    • Frontend calls trpcClient.flow.create()
    • Backend creates Flow object
    • Stored in PostgreSQL or in-memory
  2. User adds nodes and connects edges

    • Each change triggers tRPC mutations
    • Backend updates Flow
    • Flow events emitted
    • Updates sent to frontend via WebSocket
  3. User clicks "Execute Flow"

    • Frontend calls trpcClient.execution.start()
    • ExecutionService creates ExecutionContext
    • ExecutionEngine processes nodes
    • Events streamed back to frontend
  4. Node execution

    • Engine calls node.execute(context) for each node
    • Nodes read inputs, perform computation
    • Nodes update outputs
    • Events emitted for port changes
    • Frontend receives updates and renders

Type Safety

ChainGraph provides multiple layers of type safety:

  1. Compile-time: TypeScript interfaces and generics
  2. Runtime: Zod schema validation
  3. End-to-end: tRPC for client-server communication
  4. Serialization: SuperJSON for complex types

Performance Optimizations

  1. Lazy Port Instantiation - Ports created only when accessed
  2. Port Caching - Retrieved ports cached for reuse
  3. Batch Updates - Multiple port updates collected and emitted once
  4. Unified Storage - Centralized storage layer reduces overhead
  5. Event Queuing - Async event processing doesn't block execution

Technologies

Frontend

  • React - UI framework
  • Vite - Build tool and dev server
  • XYFlow - Visual graph editor
  • Effector - Reactive state management
  • tRPC Client - Type-safe API calls

Backend

  • Node.js - Runtime
  • tRPC - API framework
  • PostgreSQL - Persistent storage
  • DBOS - Durable workflow orchestration
  • Zod - Schema validation
  • SuperJSON - Serialization

Infrastructure

  • Docker - Containerization
  • pnpm - Monorepo package manager
  • Turbo - Build orchestration
  • Vitest - Testing framework

Extending ChainGraph

Creating Custom Nodes

See the Quick Start Guide for node creation examples.

Adding Custom Port Types

Extend BasePort and implement getValue() and setValue():

typescript
class MyCustomPort extends BasePort<MyType> {
  getValue(): MyType {
    // Implementation
  }

  setValue(value: MyType): void {
    // Validation and storage
  }
}

Custom Execution Strategies

Implement custom execution logic by extending ExecutionEngine or providing custom node execution methods.

Security Considerations

  • Input Validation - All port inputs validated via Zod schemas
  • Execution Sandboxing - Nodes execute in controlled contexts
  • Rate Limiting - API endpoints can be rate-limited
  • Authentication - tRPC supports authentication middleware
  • License - BUSL-1.1 for source-available protection

Limitations & Future Work

Current limitations:

  • API still evolving (breaking changes possible)
  • Some advanced features under development

Planned enhancements:

  • Enhanced DBOS workflow features
  • PostgreSQL read replicas for scaling
  • Graceful shutdown handling
  • Enhanced metrics and observability
  • Advanced retry and error handling strategies

Next Steps

License

ChainGraph is licensed under Business Source License 1.1 (BUSL-1.1).

Licensed under BUSL-1.1