Docs/Architecture/System Architecture

Architecture

System Architecture

How EasyFlow's layers fit together — API, workflow engine, messaging bus, and UI.

Overview

EasyFlow is a multi-tenant supply chain process operating system. It is built as a monorepo with five distinct layers, each with a clear responsibility. They communicate via REST APIs and an async message queue.

✦Everything is open source and self-hostable. One docker compose up command starts the full stack.

The five layers

Web app — apps/web

Next.js 14 application with Tailwind CSS and shadcn/ui. This is the product shell — the canvas, dashboards, admin portal, and all user-facing screens.

  • Business process canvas — visual drag-and-drop workflow designer built on React Flow
  • Tenant dashboards — procurement, inventory, logistics, suppliers, users per workspace
  • Globe view — animated entry point showing all tenant workspaces
  • Admin portal — super admin and tenant admin management
  • Integrations UI — n8n setup guide, webhook credentials, connector status
  • Docs site — this documentation, built in-app
  • Auth — Google OAuth + email/password via better-auth

API server — apps/api

FastAPI (Python) service that handles all business logic, access control, and data persistence.

  • Auth + RBAC — every request is verified against the actor's role and tenant scope
  • Tenant registry — create, list, update workspaces and users
  • Workflow APIs — save, retrieve, and simulate workflow definitions
  • Connector APIs — register and test ERP connections per tenant
  • Inbound webhooks — receive events from ERPs and n8n workflows
  • Notification publisher — push events to RabbitMQ for async processing
  • Alembic migrations — versioned database schema management

Workflow engine — packages/engine

Pure Python library with no framework dependencies. The engine validates workflow graphs, simulates execution, and generates execution timelines.

  • Graph validation — detects cycles, disconnected nodes, missing required fields
  • Workflow simulation — walks through a workflow definition and produces a step-by-step execution plan
  • Execution modelling — tracks state transitions, assignees, deadlines, and escalation rules
  • No database coupling — the engine is stateless and receives all context it needs as input

Async runtime — RabbitMQ + worker

RabbitMQ carries all async events between the API and the background worker. The worker consumes events, runs them through the workflow engine, and publishes results.

  • Event-driven — every workflow action is a message, not a synchronous call
  • Retry and DLQ — failed events are retried with backoff, then moved to a dead-letter queue for inspection
  • Prometheus metrics — execution counts, latency, and error rates exposed at /metrics
  • Webhook inbound — events from ERPs arrive via webhook, get normalised, and published to RabbitMQ

Connector layer — packages/connectors

Pluggable integration SDK. Each connector implements two methods: test_connection() and fetch_master_data(). The n8n / webhook pattern means most ERPs don't need a custom connector — n8n handles the ERP-specific auth and sends normalised payloads to EasyFlow.

Technology stack

LayerTechnologyWhy
FrontendNext.js 14, Tailwind CSS, shadcn/uiApp router, server components, rapid UI development
APIFastAPI, SQLAlchemy, AlembicAsync Python, auto-generated docs, type safety
DatabasePostgreSQL (Neon in production)Multi-tenant schema, reliable, scales to large datasets
Authbetter-authGoogle OAuth, email/password, session management
MessagingRabbitMQReliable async delivery, DLQ, management UI
Automationn8n (self-hosted)400+ ERP integrations, visual workflows, open source
Analytics & MLDatabricks (AWS us-east-2)Batch ML scoring for inventory risk, supplier delay, and order slip — results read via SQL Statement API
EnginePure PythonPortable, testable, no framework coupling
ContainersDocker + docker composeOne command to start everything

Monorepo structure

text
EasyFlow/
├── apps/
│   ├── api/                    FastAPI backend
│   │   ├── app/
│   │   │   ├── main.py         Application entry point + routes
│   │   │   ├── connectors.py   ERP connector CRUD APIs
│   │   │   ├── webhooks.py     Inbound webhook receiver
│   │   │   ├── access.py       RBAC — roles and tenant scoping
│   │   │   ├── models.py       SQLAlchemy ORM models
│   │   │   ├── store.py        Data access layer
│   │   │   └── worker.py       RabbitMQ consumer
│   │   └── migrations/         Alembic database migrations
│   └── web/                    Next.js frontend
│       ├── app/                App router pages
│       │   ├── page.tsx        Landing page
│       │   ├── login/          Auth pages
│       │   ├── globe/          Tenant workspace selector
│       │   ├── dashboard/      Operations dashboard
│       │   ├── workflows/      Process canvas
│       │   ├── admin/          Admin portal
│       │   ├── settings/       Integrations
│       │   └── docs/           This documentation
│       ├── components/         Shared UI components
│       └── lib/                Utilities, stores, types
├── packages/
│   ├── engine/                 Workflow execution engine
│   │   └── easyflow_engine/
│   │       ├── engine.py       Graph traversal and execution
│   │       └── models.py       Workflow data models
│   └── connectors/             ERP connector SDK
│       ├── base.py             Connector interface
│       ├── factory.py          Connector catalog + factory
│       ├── http_adapter.py     Generic HTTP connector
│       └── webhook_connector.py n8n / webhook connector
├── examples/
│   └── n8n-workflows/          Ready-to-import n8n templates
│       ├── sap-to-easyflow.json
│       └── oracle-to-easyflow.json
└── docker-compose.yml          Full stack: API + n8n + Postgres + RabbitMQ