Jeeflow: A 98KB Workflow Engine That Runs the Same Process in Java, Go, Python, and Node
If you've worked on Java business systems, you've probably encountered this scenario:
Approval flows, workflows — the moment the requirement comes in, it's "use Flowable / Activiti." Then you start wrestling with several MB of jars, hundreds of tables, and a pile of XML/JSON configurations. Bringing in an "enterprise engine" just for a "leave approval" is overkill, not to mention the learning costs, customization costs, and upgrade costs all fall on the business team.
This is the reality for many teams, and it was our real thinking back when we were building the mldong rapid development framework. Today's post is the first in the jeeflow series — I want to explain one thing clearly: how a workflow module embedded in a framework evolved step by step into an independent engine with "one set of process definitions, four language implementations."
This series continues from the mldong rapid development framework ecosystem, with synchronized updates on WeChat Official Accounts and Juejin. Welcome to follow along.
Starting Point: mldong's Built-in Custom Workflow Engine
The mldong rapid development framework (an open-source Java rapid development framework on Gitee) has a characteristic: if it can be built in-house, don't pile on dependencies. Workflow is one of those.
In an era where Flowable was everywhere, mldong chose to build its own lightweight approval engine based on LogicFlow process definitions:
- Process definitions are described using LogicFlow JSON (nodes + edges). Once drawn in the visual designer, this JSON is what gets saved;
- Supports complete approval semantics like initiation, approval, rejection, rollback, jump, countersign, carbon copy, and delegation;
- Business extensions rely on
AssignmentHandler(determines who the task is assigned to) andFlowInterceptor(pre/post node hooks), keeping business logic out of the engine; - The
wfmodules in the two open-source Java mainlines (boot2 / boot3) are completely identical, with a frontend companion vben5 process designer, ready to use out of the box.
Inside the framework, this engine ran very well: lightweight enough, stable enough, and business projects within the ecosystem could directly reuse it without reinventing the wheel.
Turning Point: Three Pain Points Forced It to "Go Independent"
As the ecosystem grew, three problems became increasingly acute:
Pain Point 1: Engine and framework coupling, high upgrade costs. The mldong framework itself underwent a "rewrite-style" evolution from boot2 to boot3 (different framework structures, business code rewritten according to logic). The engine followed the framework, meaning every major framework version upgrade forced a rewrite of the engine.
Pain Point 2: Other language teams couldn't use it. The ecosystem wasn't just Java — there was also Python (FastAPI), NestJS, and the frontend vben5. Workflow semantics are universal, but the engine was rooted in the Java framework, leaving other tech stacks "just watching."
Pain Point 3: Wanted to open it up, but couldn't carry the whole framework. Some people wanted to use this workflow engine standalone, but introducing an entire rapid development framework just for one engine was too heavy.
The conclusion was clear: The engine should have its own independent lifecycle. Its relationship with the framework should shift from "built-in module" to "upstream SDK" — the framework becomes its first consumer, not its sole host.
Independence: A 98KB Engine Core
Thus, jeeflow was born — the standalone version of the mldong workflow module. Several key design decisions:
Zero framework dependencies. The engine core (Java version) is only 98KB, with its sole dependency being slf4j-api (and that's provided). No touching Spring, no MyBatis, no Servlet.
SPI-ized. Repository, user info, JSON parsing, expression evaluation, ID generation, transaction template — 6 major SPIs. The engine makes no assumptions about your tech stack; the business side can integrate freely. Want to use MyBatis? Use MyBatis. Want an in-memory repository for unit tests? Go ahead. Want to plug in your own rule engine for expressions? That's fine too.
DDD Rich Domain Model. ProcessInstance (aggregate root) holds all state transition commands, while ProcessTask (sub-entity) is responsible for its own behavior. The state machine is explicit: Instance states are 10 In Progress / 20 Completed / 45 Rejected; Task states are 10 To Do / 20 Completed / 99 Discarded.
Contract alignment with mldong. This is the most critical part of going independent — the interface specification is completely consistent with the mldong framework: response code=0 for success, msg field, full enumeration of submitType (0 Initiate / 1 Agree / 2 Reject / 3 Return to Previous Step / 4 Jump / 5 Resubmit / 6 Return to Initiator / 20 Countersign Veto), endpoint list, VO structure, all aligned. This means: the mldong ecosystem frontend (vben5 + process designer) can directly connect to jeeflow with zero changes. Swapping the core without changing the shell, completely transparent to the consumer.
Spring Boot 2 / 3 / 4 triple starter. Comes with autoconfigure, runs from JDK 8 to 25.
Evolution: One Process Definition, Running in Four Languages
Independence wasn't the end. Back to Pain Point 2 — what about other language teams?
Our answer is a multi-language federation: not "one engine with multiple bindings," but four independent implementations + one unified specification:
- Java: The reference implementation (
jeeflow-java), the "standard answer" for all behaviors; - Go / Python / Node: Native implementations for their respective tech stacks (
jeeflow-go/jeeflow-python/jeeflow-node); - One specification (
jeeflow-doc): Data model, process definition format, state machine, SPIs, variable conventions — the single source of truth; - 10 shared process JSONs: Simple approval, multi-level approval, decision expression, parallel branch merge, parallel countersign, serial countersign, proportional countersign, custom node, process with rejection, mixed mode — the same process definition yields identical results across four languages;
- Unified frontend (
jeeflow-ui): Vue3 + DingTalk-style process designer, one UI connecting to four backends.
The evolution discipline is strict: Specification first → Java reference implementation changes and tests first → Go/Python/Node align → Cross-validation. Any language change, four demos run the same batch of processes for verification, and results must be consistent.
Now, if you open the four demo sites (Java :8080 / Go :8081 / Python :8100 / Node :8082), log in with different accounts, and run the same expense report process — the flow results are exactly the same.
Now: A Six-Repository Ecosystem
jeeflow-hub/
├── jeeflow-java # Java reference implementation (core 98KB + repository + 3 starters + demo)
├── jeeflow-go # Go implementation (GoFrame demo)
├── jeeflow-python # Python implementation (FastAPI demo)
├── jeeflow-node # Node.js implementation (Express demo)
├── jeeflow-ui # Unified frontend (Vue3 + DingTalk process designer)
└── jeeflow-doc # Specification and documentation site (jeeflow-doc.mldong.com)
Every change must pass three-scenario testing: Positive (core process runs through), Negative (boundary error codes match expectations), Regression (existing scenarios not broken). Test matrix: Java core 14 + jdbc 5, Python spec 10 + e2e 34, Node 10. Untested code is not allowed to be committed — this discipline runs through all languages.
What I'll Write in This Series
The jeeflow series has four seasons, synchronized on WeChat Official Accounts and Juejin:
| Season | Theme | Articles |
|---|---|---|
| Prologue | From mldong to jeeflow (this post) | Part 0 |
| Season 1 · Understanding | Why build it yourself, what the 98KB looks like, state machine and submitType | 3 articles |
| Season 2 · Core Design | LogicFlow JSON, DDD aggregate root, applicant contract, 6 major SPIs, the three countersign brothers | 5 articles |
| Season 3 · Multi-language Federation | One definition running in four languages, cross-language alignment methodology, comparison of four implementations | 3 articles |
| Season 4 · Ecosystem in Practice | mldong contract alignment, Spring Boot 2/3/4 starter, jeeflow-ui, expense report process in practice, three-scenario testing | 5 articles |
Next post preview: 《Why Write a Lightweight Workflow Engine in the Flowable Era》 — a complete selection comparison between self-built vs mainstream open-source engines, thoroughly explaining "should you build it yourself."
Related Links
- Engine repositories (GitHub · mldong organization):
jeeflow-java/jeeflow-go/jeeflow-python/jeeflow-node/jeeflow-ui - Specification and documentation site: https://jeeflow-doc.mldong.com
- Demo sites: Java :8080 · Go :8081 · Python :8100 · Node :8082 · UI :5173
- Upstream framework: mldong rapid development framework (open source on Gitee, with built-in custom workflow engine)
Top 1 from juejin.cn, machine-translated. The original thread is authoritative.
The multi-language isomorphic approach is very clear.