Skip to content

ION Flow - System Architecture

Comprehensive documentation of the ION Flow workflow automation system architecture, module relationships, and external library dependencies.


ION Flow is a modular workflow automation system built in Go with a layered architecture designed for:

  • Modularity - Independent, self-contained modules
  • Portability - Reusable packages across projects
  • Scalability - Multi-tenant support with isolated data
  • Real-time Execution - WebSocket-based flow monitoring

The system uses a Go workspace monorepo pattern with module replace directives, allowing independent development while maintaining cross-module dependencies.


ion-binaries/
├── core/ # Flow execution engine (the heart)
├── backend/ # ION Flow backend with auth & real-time features
├── server/ # REST microservice for flow APIs
├── packages/ # Reusable generic modules
│ ├── channel/ # Authentication engine (OAuth, API Key)
│ └── helpers/ # Generic utility functions
└── cli/ # DEPRECATED - Multi-language CLI experiment
ModulePurposeStatus
core/Flow execution engineActive
backend/ION Flow backend with WebSocket supportActive
server/REST microservice for flow executionActive
packages/Reusable portable modulesActive
cli/Multi-language CLIDeprecated

graph TB
subgraph packages [packages - Portable Modules]
helpers[helpers]
channel[channel]
end
subgraph core [core - Flow Engine]
coreActions[actions]
coreModels[models]
coreServices[services]
coreDb[db - SQLite]
coreLibs[libs]
end
subgraph backend [backend - ION Backend]
board[board - WebSocket Engine]
controllers[controllers]
backendServices[services]
nodes[nodes]
end
subgraph server [server - REST Microservice]
serverControllers[controllers]
end
channel --> helpers
channel --> core
backend --> core
backend --> channel
backend --> helpers
server --> core
  1. Core - Has no dependencies on other internal modules (only external libraries)
  2. Packages - Self-contained, can depend on each other but not on core/backend
  3. Channel - Depends on helpers and core models
  4. Backend - Depends on core, channel, and helpers
  5. Server - Depends only on core

The heart of ION Flow - responsible for flow execution, state management, and node processing.

core/
├── actions/ # Node type implementations
│ ├── flow/ # Main flow control API
│ ├── condition/ # Conditional logic nodes
│ ├── switchnode/ # Switch/case nodes
│ ├── mapper/ # Data mapping nodes
│ ├── transformer/# Data transformation nodes
│ ├── iterator/ # Loop/iteration nodes
│ ├── timer/ # Timer/delay nodes
│ └── store/ # Data storage nodes
├── models/ # Data structures (Node, Queue, Stack, Edge)
├── services/ # Business logic (node, queue, stack, edge services)
├── helpers/ # Core-specific utilities
├── libs/ # External library wrappers (expression language)
├── db/ # SQLite database operations
└── global/ # Global constants and variables
FunctionPurposeSignature
LoadFlowCreates new SQLite workspace and initializes flowLoadFlow(flowId string, flow models.Flow) error
RunNodeStarts execution of a specific nodeRunNode(flowId string, nodeId string, targetId string) (*models.Response, error)
PushNodePushes results and continues to connected nodesPushNode(flowId string, ots []models.Ot, message string, status string, clientPath string) (*models.Result, error)
ContinueNodeGets next node from queue and prepares executionContinueNode(flowId string) (*models.Response, error)
LibraryVersionPurpose
github.com/expr-lang/exprv1.17.2Expression language for dynamic parameter evaluation in node data
github.com/google/uuidv1.6.0UUID generation for flow and node identifiers
github.com/mattn/go-sqlite3v1.14.24SQLite driver for flow state persistence

The main ION Flow backend - extends core with authentication, multi-tenancy, and real-time features.

backend/
├── ion/
│ ├── board/ # WebSocket flow execution engine
│ ├── controllers/ # REST API controllers
│ ├── services/ # Business logic services
│ ├── models/ # Backend-specific models
│ ├── nodes/ # Platform-specific node implementations
│ ├── params/ # DTOs for controller parameters
│ ├── helpers/ # Backend-specific utilities
│ ├── middleware/ # HTTP middleware (auth, logging)
│ ├── database/ # Database connection management
│ ├── scheduler/ # Cron job scheduling
│ └── workspace/ # Flow workspace management
└── routes/
├── api.go # REST API routes
└── channels.go # WebSocket routes

The WebSocket-based execution engine for real-time flow monitoring:

ComponentFilePurpose
ExecutionEngineengine.goManages flow execution lifecycle
Hubhub.goWebSocket connection management
CompanyDevFlowcompany_dev_flow.goDevelopment mode execution
CompanyLiveFlowcompany_live_flow.goProduction mode execution
AccountDevFlowaccount_dev_flow.goAccount development mode
AccountLiveFlowaccount_live_flow.goAccount live mode
StatusDescription
pendingWaiting to start
runningCurrently executing
pausedExecution paused
waiting_inputWaiting for user input via WebSocket
stoppedManually stopped
completedSuccessfully finished
errorFailed with error
LibraryVersionPurpose
github.com/gorilla/muxv1.8.1HTTP router for REST API endpoints
github.com/gorilla/websocketv1.5.3WebSocket support for real-time flow execution
github.com/golang-jwt/jwt/v5v5.2.1JWT authentication and token validation
github.com/robfig/cron/v3v3.0.1Cron job scheduling for scheduled flows
github.com/rs/corsv1.11.1CORS middleware for API access control
github.com/joho/godotenvv1.5.1Environment variable loading from .env files
github.com/go-git/go-git/v6v6.0.0Git operations for flow version control
github.com/stretchr/testifyv1.11.1Testing utilities and assertions
gorm.io/gormv1.30.0ORM for database operations
gorm.io/driver/postgresv1.5.11PostgreSQL driver for multi-tenant data
gorm.io/driver/sqlitev1.4.3SQLite driver for local storage
gorm.io/datatypesv1.2.6GORM JSON and custom data types

A lightweight REST microservice that exposes core flow APIs for external consumption.

EndpointMethodPurpose
/loadPOSTLoad flow into workspace
/runPOSTRun initial node
/continuePOSTContinue to next node
/pushPOSTPush node results
/interruptPOSTInterrupt execution
/mapperPOSTExecute mapper
/data-store-*VariousData store CRUD operations
/data-structure-*VariousData structure CRUD operations

Server inherits dependencies from core and adds minimal HTTP handling:

LibraryVersionPurpose
github.com/mattn/go-sqlite3v1.14.24SQLite driver (inherited from core)

Reusable, portable modules designed to work independently.

Authentication engine supporting multiple auth types:

packages/channel/
├── core/ # Core authentication service
├── services/ # Auth flow services
│ ├── authorize.go # Authorization flow handling
│ ├── token.go # Token retrieval
│ ├── refresh.go # Token refresh logic
│ ├── callback.go # OAuth callback handling
│ ├── info.go # Connection info retrieval
│ └── response.go # Response processing
└── models/ # Authentication models
├── app.go # App configuration
├── app_action.go # App action definitions
├── app_connection.go # Connection configuration
├── app_webhook.go # Webhook configuration
├── connection.go # Active connections
└── field.go # Field definitions
TypeDescription
oauth2_codeOAuth 2.0 Authorization Code flow
oauth2_code_refresh_tokenOAuth 2.0 with automatic token refresh
api_keyAPI Key authentication
basicHTTP Basic authentication
client_credentialsOAuth 2.0 Client Credentials grant
owner_credentialsOAuth 2.0 Resource Owner Password grant
LibraryVersionPurpose
gorm.io/datatypesv1.2.6JSON field support for OAuth tokens and credentials

Generic utility functions:

packages/helpers/
├── config.go # Configuration parsing utilities
├── sanitizer.go # JSON/JSONC sanitization
└── pointers.go # Pointer helper functions
FunctionFilePurpose
ParseStringWithDefaultconfig.goParse string with fallback
ParseIntWithDefaultconfig.goParse integer with fallback
ParseBoolWithDefaultconfig.goParse boolean with fallback
SanitizeJSONCsanitizer.goRemove comments from JSONC
ParseJSONCsanitizer.goParse JSONC to map
ParseJSONCArraysanitizer.goParse JSONC to array
ParseJSONCToTypesanitizer.goGeneric JSONC to type parsing

The execution model follows a pointer-based pattern similar to database cursors:

sequenceDiagram
participant Client
participant Engine as Board Engine
participant Core as Core Flow
participant DB as SQLite
Client->>Engine: Start Flow
Engine->>Core: LoadFlow(flowId, flow)
Core->>DB: Create workspace
Engine->>Core: RunNode(flowId, nodeId)
Core->>DB: Get node, update status
Core-->>Engine: Response with queue
loop While queue has items
Engine->>Core: PushNode(flowId, ots)
Core->>DB: Push to queue
Core-->>Engine: Result
Engine->>Core: ContinueNode(flowId)
Core->>DB: Pop queue, get next node
Core-->>Engine: Response or null
end
Engine-->>Client: Execution complete
ModuleStoragePurpose
CoreSQLite filesFlow execution state, node data, queues
BackendPostgreSQLMulti-tenant data, accounts, companies
BackendSQLiteLocal workspace storage

The backend supports two database connection patterns:

For data shared across tenants:

// Uses global database connection
if err := database.GetConnection().
Model(&model).
Where("id = ?", id).
First(&result).Error; err != nil {
return nil, err
}

For company-isolated data:

// Uses company schema for tenant isolation
if err := company.CompanySchema(models.TableName()).
Where("id = ?", id).
First(&result).Error; err != nil {
return nil, err
}

flowchart TD
A[Start Auth] --> B{Auth Type?}
B -->|oauth2_code| C[Generate Auth URL]
C --> D[Redirect to Provider]
D --> E[Callback with Code]
E --> F[Exchange for Token]
F --> G[Get User Info]
B -->|api_key| H[Make Test Request]
H --> I[Process Response]
B -->|client_credentials| J[Get Token]
J --> K[Get Info]
B -->|basic| L[Make Auth Request]
L --> M[Process Response]
G --> N[Return Connection]
I --> N
K --> N
M --> N

CategoryTechnologyVersion
LanguageGo1.24.3
HTTP RouterGorilla Mux1.8.1
WebSocketGorilla WebSocket1.5.3
ORMGORM1.30.0
Primary DatabasePostgreSQL-
State StorageSQLite3.x
Expression Languageexpr-lang/expr1.17.2
AuthenticationJWT5.2.1
Job Schedulingrobfig/cron3.0.1
Version Controlgo-git6.0.0