go-bpm RU

Open source · Go · PostgreSQL

Draw processes in BPMN.
Run them as Go code.

go-bpm turns BPMN diagrams and DMN decision tables into typed Go code and runs it on a PostgreSQL task queue, in the same database as your service data. The engine is a library inside your service. Test methods and decisions with ordinary go test.

Tested on Astra Linux Special Edition 1.8.1.6 →

$ go get github.com/nicolas-vp/go-bpm
process/order.bpmn
Order approval: validation, a gateway, manager approval and customer notification (Russian diagram labels)
order_approval/method_check_order.go
func CheckOrder(ctx context.Context, svc *services.Services,
    data *model.DataModel) error {
    if data.Amount <= 0 {
        return fmt.Errorf("amount must be positive")
    }
    data.Checked = true
    return nil
}

How it works

  1. 1

    Draw a process

    Use go-bpm modeler, with supported elements and generator validation. Camunda Modeler diagrams work too: go-bpm reads gobpm:* and zeebe:* extensions. Keep BPMN and DMN files in process/ and review them alongside code.

  2. 2

    Generate Go code

    go-bpm-gen validates the diagram and generates transitions, gateway conditions, scripts, DMN decisions and method stubs. The compiler catches errors in expressions.

  3. 3

    Run your service

    The engine runs each process step as a PostgreSQL queue task. All database effects of a step commit in one transaction.

Why go-bpm

A process is code

Gateway conditions, scripts and DMN tables become Go functions before startup. A gateway condition is an ordinary if.

One step, one transaction

Token movement, history and new tasks commit together with queue task completion. If the service crashes halfway through, the whole step is retried.

Typed process data

Your DataModel holds process variables. Methods work with struct fields instead of map[string]any.

Only PostgreSQL required

The queue, history, instances and user tasks live in bpm_* tables. Scale your service with multiple workers sharing one database.

Start in your transaction

StartProcessTx starts a process in the same transaction as your business data: an order and its process appear together or neither appears.

A console included

/ui/ provides processes, instance search, user tasks, diagram history, matched DMN rules, heatmaps and process statistics.

Testing

Tests are ordinary go test

Business logic lives in Go functions. Test it like the rest of your service.

  • Task methods: call a function with *model.DataModel and check its fields.
  • External dependencies: inject stubs through interfaces in services.Services.
  • DMN decisions: test generated decide<Id> functions from the process package.
  • Entire processes: start an instance on a real PostgreSQL database and wait for its result.
  • Diagram errors: generation and compilation catch invalid expressions and variable types.
func TestCheckOrder(t *testing.T) {
    data := &model.DataModel{Amount: 500}
    err := CheckOrder(context.Background(), &services.Services{}, data)
    if err != nil { t.Fatal(err) }
    if !data.Checked { t.Error("order was not checked") }
}

Configuration and extension

Fits your service

Assemble the engine, API and console inside your Go service.

Your dependencies

Database, API and queue clients are typed fields of services.Services, available to methods and handlers.

Your data model

Process variables are fields of your DataModel, including nested structs.

Your code is preserved

Method, handler and model stubs are created once. Only files marked Code generated by go-bpm-gen are regenerated.

Your HTTP and authorization

Register API and console handlers on your http.ServeMux and protect them with your middleware.

Your migrations

Use migrations.Up or take SQL from migrations.List() for goose, migrate or liquibase.

Engine settings

Configure workers, attempts, timeouts, retry delays, slog logging, live history flags and queue prefixes for process versions.

Prometheus metrics

metrics.Collector exposes queue states, oldest task age, failed instances, open user tasks and attempt durations.

Hooks and tracing

engine.Hooks provides element events, a wrapper for your code and instance failure notifications. Add OpenTelemetry spans and alerts.

History retention

engine.Retention deletes old completed and cancelled instances with their history and tasks. Failed instances remain available for investigation.

Engine configuration, hooks and metrics

What the engine supports

The generator rejects unsupported BPMN during generation.

  • Tasks, script tasks and service tasks with retries
  • Exclusive and parallel gateways
  • DMN business rule tasks compiled into Go
  • AI tasks with text or JSON output into the data model
  • User tasks with assignees, candidates and groups
  • Duration and date timers; boundary timer and error events
  • User task escalation with boundary timers
  • Receive tasks and message events with key correlation
  • Sequential multi-instance with a count and completion condition
  • Embedded subprocesses and call activities
  • Business keys and persisted instance history
  • HTTP APIs, failed step retries and instance cancellation
  • Heatmaps and process statistics

Elements and limitations

Supported BPMN elements (Russian labels)

Embed it in your service

Connect the engine, API and console to your http.ServeMux and pgx pool.

go get github.com/nicolas-vp/go-bpm
go get -tool github.com/nicolas-vp/go-bpm/cmd/go-bpm-gen
q := queue.New(pool, queue.Options{})
e, _ := engine.New(q, engine.Config{
    History:      engine.HistoryConfig{ToDB: on},
    RulesHistory: engine.HistoryConfig{ToDB: on},
}, bpmgen.Processes(svc), bpmgen.Queues(svc))

httpapi.Register(mux, e, history)
webui.Register(mux, history)
q.Start(ctx)

Build your service step by step

Instance history on the diagram

Follow tokens, inspect task variables and see which DMN rules matched. Screenshots show the Russian console.

Operations

Recover failures and find slow steps

Use the console, HTTP API or Go methods.

Retry a failed step

Inspect the failed element, attempt count and error. Deploy a fix and return the task to the queue. Its instance and parents resume.

Fix variables

Edit token variables as JSON and retry the task with corrected data.

Cancel an instance

Cancel a root instance and its children, removing queued tasks, timers and open user tasks.

Heatmap

Color diagram elements by average, maximum or total duration, or execution count, for a selected period.

Statistics

See instance outcomes by start date, plus median and p95 completion time.

Your tools

Use failure, retry, cancellation, heatmap and statistics HTTP endpoints or engine.InstanceOperations.

Operations API