Skip to content

fsm_core

Finite state machine toolkit for PostgreSQL

fsm_core : Finite state machine toolkit for PostgreSQL

Overview

ID Extension Package Version Category License Language
2690 fsm_core fsm_core 1.1.0 FEAT Apache-2.0 SQL
Attribute Has Binary Has Library Need Load Has DDL Relocatable Trusted
----d-- No No No Yes no no
Relationships
Schemas fsm_core
Requires ltree pgmq pg_jsonschema
See Also pgmq ulak pgmb pg_durable redis pg_task pg_background pgq redis_fdw tcn
PG15+; requires ltree, pgmq, and pg_jsonschema

Packages

Type Repo Version PG Major Compatibility Package Pattern Dependencies
EXT PIGSTY 1.1.0 18 17 16 15 14 fsm_core ltree, pgmq, pg_jsonschema
RPM PIGSTY 1.1.0 18 17 16 15 14 fsm_core_$v pgmq_$v
DEB PIGSTY 1.1.0 18 17 16 15 14 postgresql-$v-fsm-core postgresql-$v-pgmq, postgresql-$v-pg-jsonschema
Linux / PG PG18 PG17 PG16 PG15 PG14
el8.x86_64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
el8.aarch64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
el9.x86_64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
el9.aarch64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
el10.x86_64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
el10.aarch64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
d12.x86_64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
d12.aarch64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
d13.x86_64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
d13.aarch64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
u22.x86_64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
u22.aarch64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
u24.x86_64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
u24.aarch64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
u26.x86_64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
u26.aarch64 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 PIGSTY 1.1.0 N/A
Package Version OS ORG SIZE File URL
fsm_core_18 1.1.0 el8.x86_64 pigsty 33.0 KiB fsm_core_18-1.1.0-1PIGSTY.el8.x86_64.rpm
fsm_core_18 1.1.0 el8.aarch64 pigsty 33.0 KiB fsm_core_18-1.1.0-1PIGSTY.el8.aarch64.rpm
fsm_core_18 1.1.0 el9.x86_64 pigsty 30.8 KiB fsm_core_18-1.1.0-1PIGSTY.el9.x86_64.rpm
fsm_core_18 1.1.0 el9.aarch64 pigsty 30.7 KiB fsm_core_18-1.1.0-1PIGSTY.el9.aarch64.rpm
fsm_core_18 1.1.0 el10.x86_64 pigsty 30.9 KiB fsm_core_18-1.1.0-1PIGSTY.el10.x86_64.rpm
fsm_core_18 1.1.0 el10.aarch64 pigsty 30.8 KiB fsm_core_18-1.1.0-1PIGSTY.el10.aarch64.rpm
postgresql-18-fsm-core 1.1.0 d12.x86_64 pigsty 24.4 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~bookworm_all.deb
postgresql-18-fsm-core 1.1.0 d12.aarch64 pigsty 24.4 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~bookworm_all.deb
postgresql-18-fsm-core 1.1.0 d13.x86_64 pigsty 24.4 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~trixie_all.deb
postgresql-18-fsm-core 1.1.0 d13.aarch64 pigsty 24.4 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~trixie_all.deb
postgresql-18-fsm-core 1.1.0 u22.x86_64 pigsty 24.7 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~jammy_all.deb
postgresql-18-fsm-core 1.1.0 u22.aarch64 pigsty 24.7 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~jammy_all.deb
postgresql-18-fsm-core 1.1.0 u24.x86_64 pigsty 24.7 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~noble_all.deb
postgresql-18-fsm-core 1.1.0 u24.aarch64 pigsty 24.7 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~noble_all.deb
postgresql-18-fsm-core 1.1.0 u26.x86_64 pigsty 24.7 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~resolute_all.deb
postgresql-18-fsm-core 1.1.0 u26.aarch64 pigsty 24.7 KiB postgresql-18-fsm-core_1.1.0-1PIGSTY~resolute_all.deb
Package Version OS ORG SIZE File URL
fsm_core_17 1.1.0 el8.x86_64 pigsty 33.0 KiB fsm_core_17-1.1.0-1PIGSTY.el8.x86_64.rpm
fsm_core_17 1.1.0 el8.aarch64 pigsty 33.0 KiB fsm_core_17-1.1.0-1PIGSTY.el8.aarch64.rpm
fsm_core_17 1.1.0 el9.x86_64 pigsty 30.7 KiB fsm_core_17-1.1.0-1PIGSTY.el9.x86_64.rpm
fsm_core_17 1.1.0 el9.aarch64 pigsty 30.7 KiB fsm_core_17-1.1.0-1PIGSTY.el9.aarch64.rpm
fsm_core_17 1.1.0 el10.x86_64 pigsty 30.9 KiB fsm_core_17-1.1.0-1PIGSTY.el10.x86_64.rpm
fsm_core_17 1.1.0 el10.aarch64 pigsty 30.8 KiB fsm_core_17-1.1.0-1PIGSTY.el10.aarch64.rpm
postgresql-17-fsm-core 1.1.0 d12.x86_64 pigsty 24.4 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~bookworm_all.deb
postgresql-17-fsm-core 1.1.0 d12.aarch64 pigsty 24.4 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~bookworm_all.deb
postgresql-17-fsm-core 1.1.0 d13.x86_64 pigsty 24.4 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~trixie_all.deb
postgresql-17-fsm-core 1.1.0 d13.aarch64 pigsty 24.4 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~trixie_all.deb
postgresql-17-fsm-core 1.1.0 u22.x86_64 pigsty 24.7 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~jammy_all.deb
postgresql-17-fsm-core 1.1.0 u22.aarch64 pigsty 24.7 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~jammy_all.deb
postgresql-17-fsm-core 1.1.0 u24.x86_64 pigsty 24.7 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~noble_all.deb
postgresql-17-fsm-core 1.1.0 u24.aarch64 pigsty 24.7 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~noble_all.deb
postgresql-17-fsm-core 1.1.0 u26.x86_64 pigsty 24.7 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~resolute_all.deb
postgresql-17-fsm-core 1.1.0 u26.aarch64 pigsty 24.7 KiB postgresql-17-fsm-core_1.1.0-1PIGSTY~resolute_all.deb
Package Version OS ORG SIZE File URL
fsm_core_16 1.1.0 el8.x86_64 pigsty 33.0 KiB fsm_core_16-1.1.0-1PIGSTY.el8.x86_64.rpm
fsm_core_16 1.1.0 el8.aarch64 pigsty 33.0 KiB fsm_core_16-1.1.0-1PIGSTY.el8.aarch64.rpm
fsm_core_16 1.1.0 el9.x86_64 pigsty 30.8 KiB fsm_core_16-1.1.0-1PIGSTY.el9.x86_64.rpm
fsm_core_16 1.1.0 el9.aarch64 pigsty 30.7 KiB fsm_core_16-1.1.0-1PIGSTY.el9.aarch64.rpm
fsm_core_16 1.1.0 el10.x86_64 pigsty 30.9 KiB fsm_core_16-1.1.0-1PIGSTY.el10.x86_64.rpm
fsm_core_16 1.1.0 el10.aarch64 pigsty 30.8 KiB fsm_core_16-1.1.0-1PIGSTY.el10.aarch64.rpm
postgresql-16-fsm-core 1.1.0 d12.x86_64 pigsty 24.4 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~bookworm_all.deb
postgresql-16-fsm-core 1.1.0 d12.aarch64 pigsty 24.4 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~bookworm_all.deb
postgresql-16-fsm-core 1.1.0 d13.x86_64 pigsty 24.4 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~trixie_all.deb
postgresql-16-fsm-core 1.1.0 d13.aarch64 pigsty 24.4 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~trixie_all.deb
postgresql-16-fsm-core 1.1.0 u22.x86_64 pigsty 24.7 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~jammy_all.deb
postgresql-16-fsm-core 1.1.0 u22.aarch64 pigsty 24.7 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~jammy_all.deb
postgresql-16-fsm-core 1.1.0 u24.x86_64 pigsty 24.7 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~noble_all.deb
postgresql-16-fsm-core 1.1.0 u24.aarch64 pigsty 24.7 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~noble_all.deb
postgresql-16-fsm-core 1.1.0 u26.x86_64 pigsty 24.7 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~resolute_all.deb
postgresql-16-fsm-core 1.1.0 u26.aarch64 pigsty 24.7 KiB postgresql-16-fsm-core_1.1.0-1PIGSTY~resolute_all.deb
Package Version OS ORG SIZE File URL
fsm_core_15 1.1.0 el8.x86_64 pigsty 33.0 KiB fsm_core_15-1.1.0-1PIGSTY.el8.x86_64.rpm
fsm_core_15 1.1.0 el8.aarch64 pigsty 33.0 KiB fsm_core_15-1.1.0-1PIGSTY.el8.aarch64.rpm
fsm_core_15 1.1.0 el9.x86_64 pigsty 30.7 KiB fsm_core_15-1.1.0-1PIGSTY.el9.x86_64.rpm
fsm_core_15 1.1.0 el9.aarch64 pigsty 30.7 KiB fsm_core_15-1.1.0-1PIGSTY.el9.aarch64.rpm
fsm_core_15 1.1.0 el10.x86_64 pigsty 30.9 KiB fsm_core_15-1.1.0-1PIGSTY.el10.x86_64.rpm
fsm_core_15 1.1.0 el10.aarch64 pigsty 30.8 KiB fsm_core_15-1.1.0-1PIGSTY.el10.aarch64.rpm
postgresql-15-fsm-core 1.1.0 d12.x86_64 pigsty 24.4 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~bookworm_all.deb
postgresql-15-fsm-core 1.1.0 d12.aarch64 pigsty 24.4 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~bookworm_all.deb
postgresql-15-fsm-core 1.1.0 d13.x86_64 pigsty 24.4 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~trixie_all.deb
postgresql-15-fsm-core 1.1.0 d13.aarch64 pigsty 24.4 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~trixie_all.deb
postgresql-15-fsm-core 1.1.0 u22.x86_64 pigsty 24.7 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~jammy_all.deb
postgresql-15-fsm-core 1.1.0 u22.aarch64 pigsty 24.7 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~jammy_all.deb
postgresql-15-fsm-core 1.1.0 u24.x86_64 pigsty 24.7 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~noble_all.deb
postgresql-15-fsm-core 1.1.0 u24.aarch64 pigsty 24.7 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~noble_all.deb
postgresql-15-fsm-core 1.1.0 u26.x86_64 pigsty 24.7 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~resolute_all.deb
postgresql-15-fsm-core 1.1.0 u26.aarch64 pigsty 24.7 KiB postgresql-15-fsm-core_1.1.0-1PIGSTY~resolute_all.deb

Source

github.com/pgfsm/fsm/tree/main/packages/database-src-extension/fsm_core

pig build pkg fsm_core;		# build rpm/deb

Install

Make sure PGDG and PIGSTY repo available:

pig repo add pgsql -u   # add both repo and update cache

Install this extension with pig:

pig install fsm_core;		# install via package name, for the active PG version

pig install fsm_core -v 18;   # install for PG 18
pig install fsm_core -v 17;   # install for PG 17
pig install fsm_core -v 16;   # install for PG 16
pig install fsm_core -v 15;   # install for PG 15

Create this extension with:

CREATE EXTENSION fsm_core CASCADE; -- requires ltree, pgmq, pg_jsonschema

Usage

Sources:

fsm_core is a finite-state-machine toolkit that stores FSM definitions, instances, transitions, and event logs inside PostgreSQL. A machine definition is loaded from JSON, instances are created by name and version, and events are sent through SQL functions with optional pgmq queues.

This document describes the PGXN 1.1.0 distribution, which requires PostgreSQL 15 or later, ltree 1.2 or later and pgmq 1.4.4 or later. The fixed schema is fsm_core; installation requires a superuser. No preload or restart is required by this SQL extension. Current repository migrations are a separate source and may expose a different API.

Core Tables and Types

fsm_core creates an enum fsm_state_type with atomic, compound, parallel, final, and history, plus tables including:

  • fsm_core.fsm_json for loaded FSM definitions.
  • fsm_core.fsm_states for expanded state nodes and ltree paths.
  • fsm_core.fsm_transitions for transition rules.
  • fsm_core.fsm_instance for running instances.
  • fsm_core.fsm_instance_lock for advisory/concurrency state.
  • fsm_core.fsm_instance_queue_event_logs and fsm_core.fsm_promise_queue_event_logs for queued event history.

Load a Machine Definition

SELECT fsm_core.load_fsm_from_json_v2(
  json_input        := :'fsm_json'::jsonb,
  root_node_text    := 'root',
  input_fsm_type    := 'workflow',
  input_fsm_name    := 'creditCheck',
  input_fsm_version := 'v01'
);

load_fsm_from_json_v2() checks JSON against fsm_core.fsm_json_schema(), expands states and transitions, then caches the raw definition in fsm_json. In 1.1.0, JSON-schema violations produce a NOTICE and loading continues; the schema-validation exception is commented out. Validate definitions before loading rather than relying on this check to reject every invalid definition. Keep deployed definitions and version identifiers stable so existing instances continue against their original definition. Set the psql variable fsm_json to your validated machine JSON before running the example.

Create an Instance

SELECT fsm_core.create_fsm_instance_from_name_v2(
  input_fsm_name     := 'creditCheck',
  input_fsm_version  := 'v01',
  input_fsm_context  := '{"applicant_id":"a-42"}'::jsonb,
  create_pgmq_queue  := true
) AS creation_result
\gset
SELECT :'creation_result'::jsonb AS creation_status;
SELECT :'creation_result'::jsonb ->> 'fsm_instance_id' AS fsm_instance_id
\gset

The PGXN 1.1.0 function checks that the named FSM exists, inserts an fsm_instance, and copies transition authorization rows. When create_pgmq_queue is true, it attempts to create a pgmq queue named by the instance UUID and send initialTransition_event. Queue creation and initial-event failures are caught and reported in the returned JSON. Before sending further events, require queue_created to be true and inspect send_event_result, message and extra_message to confirm the initial event succeeded. The psql example retains the returned fsm_instance_id for the next call.

Send Events

SELECT fsm_core.send_event_to_fsm_queue_with_event_logs_v2(
  input_fsm_instance_id                 := :'fsm_instance_id'::uuid,
  input_fsm_instance_id_fsm_type         := 'workflow',
  input_fsm_instance_id_fsm_version      := 'v01',
  input_send_to_parent_queue_id          := fsm_core.pg_system_queue_uuid(),
  input_send_to_parent_queue_type        := fsm_core.pg_system_queue_type(),
  input_send_to_parent_queue_id_event_name := fsm_core.pg_system_event_name(),
  input_event_name                       := 'APPROVE',
  input_event_action_type                := 'user',
  input_event_data                       := '{"approved_by":"manager"}'::jsonb,
  input_event_delay                      := 0
);

This helper writes to the instance queue with pgmq.send() and records the event in fsm_instance_queue_event_logs. For nested FSM and promise flows, send_event_to_queue_from_fsm_instance_id_v2() dispatches to the child-FSM or promise queue helper based on fsmtype.

Resolve and Step State

SELECT fsm_core.resolve_state_value_v2(
  input_json        := '{"value":"pending"}'::jsonb,
  input_fsm_name    := 'creditCheck',
  input_fsm_version := 'v01'
);

SELECT fsm_core.macrostep_v2(
  event_name        := 'APPROVE',
  input_state_value := ARRAY['pending']::text[],
  fsm_name_param    := 'creditCheck',
  fsm_version_param := 'v01'
);

The SQL surface also includes lower-level microstep_v2(), fsm_worker_v2(), lock helpers, archive helpers, and v1 compatibility functions. Prefer v2 entry points for new usage when both versions are present.

Dependencies and Operation

Enable ltree and pgmq before installing fsm_core. The release README also requires pg_jsonschema 0.3.3 or later, although the control and META dependency lists omit it. The JSON loader calls fsm_core.jsonschema_validation_errors, which is not defined by the distribution’s SQL script; verify that the documented JSON-schema helper is available in that schema before loading definitions. Installing a dependency into a different schema alone does not provide that qualified function.

Queued events persist as application data. Supplying create_pgmq_queue => true requests the per-instance queue and its initial event; check the returned status before proceeding. A consumer still needs to process queued work. Sending an event does not by itself guarantee that an asynchronous worker has executed the transition. Review queue retention, consumers and permissions together.

Inspect function and table grants before exposing machine creation or arbitrary event submission to application roles. The SQL surface also contains legacy v1 and lower-level helpers; use the verified v2 entry points for this release.