fsm_core
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
pg_jsonschema
pg_task
pg_later
pg_cron
|
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
|
MISS
|
el8.aarch64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
el9.x86_64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
el9.aarch64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
el10.x86_64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
el10.aarch64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
d12.x86_64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
d12.aarch64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
d13.x86_64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
d13.aarch64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
u22.x86_64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
u22.aarch64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
u24.x86_64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
u24.aarch64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
u26.x86_64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
u26.aarch64
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
PIGSTY 1.1.0
|
MISS
|
Source
pig build pkg fsm_core; # build rpm/debInstall
Make sure PGDG and PIGSTY repo available:
pig repo add pgsql -u # add both repo and update cacheInstall 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 15Create this extension with:
CREATE EXTENSION fsm_core CASCADE; -- requires ltree, pgmq, pg_jsonschemaUsage
Sources:
- fsm_core PGXN README
- PGXN control file
- 1.1.0 SQL definition
- Supabase 1.1.1-1.1.3 migrations
- worker execution ADR
- example definitions README
fsm_core is a finite-state-machine toolkit that stores FSM definitions, instances, transitions, dispatch queues, 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 or the newer scheduler dispatch path.
The PGXN packaged extension still declares default_version = '1.1.0' and requires PostgreSQL 15+, ltree, and pgmq. The repository’s packages/database-src project is at 1.1.3 and contains Supabase migration files through fsm_core--1.1.2--1.1.3.sql; the Rust/pgrx directory is explicitly marked not currently used. Treat the PGXN distribution as the packaged source and the Supabase migrations as main-branch material.
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_jsonfor loaded FSM definitions.fsm_core.fsm_statesfor expanded state nodes and ltree paths.fsm_core.fsm_transitionsfor transition rules.fsm_core.fsm_instancefor running instances.fsm_core.fsm_instance_lockfor advisory/concurrency state.fsm_core.fsm_instance_queue_event_logsandfsm_core.fsm_promise_queue_event_logsfor queued event history.fsm_core.fsm_dispatch_queueandfsm_core.fsm_daemon_nodein the main-branch scheduler path.
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() validates JSON with fsm_core.fsm_json_schema(), caches the raw definition in fsm_json, then expands states and transitions. Upstream examples keep immutable version folders such as fsm/creditCheck/v01/xstate-fsm.json and fsm/creditCheck/v02/xstate-fsm.json; keep deployed versions immutable so existing instances continue against their original definition.
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
);The PGXN 1.1.0 function checks that the named FSM exists, inserts an fsm_instance, copies transition authorization rows for that instance, and, when create_pgmq_queue is true, creates a pgmq queue named by the instance UUID and sends initialTransition_event.
The main-branch Supabase schema also has a scheduler-oriented path where instance creation can enqueue work through fsm_core.enqueue_fsm_dispatch_v2() instead of relying only on per-instance pgmq queues.
Send Events
SELECT fsm_core.send_event_to_fsm_queue_with_event_logs_v2(
input_fsm_instance_id := '00000000-0000-0000-0000-000000000000'::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.
Scheduler Dispatch Path
SELECT fsm_core.enqueue_fsm_dispatch_v2(
input_instance_id := '00000000-0000-0000-0000-000000000000'::uuid,
input_fsm_name := 'creditCheck',
input_fsm_version := 'v01',
input_dispatch_type := 'start'
);
SELECT fsm_core.schedule_next_pending();The newer worker design uses fsm_dispatch_queue as the source of pending work and fsm_daemon_node as the registry of available fsmlet nodes. enqueue_fsm_dispatch_v2() inserts a pending dispatch row and emits pg_notify('fsm_scheduler_work', instance_id). schedule_next_pending() selects pending rows with FOR UPDATE SKIP LOCKED, chooses a daemon under its concurrency limit, marks the row scheduled, and notifies fsm_fsmlet_work_<daemon_id>.
This scheduler path appears in the main-branch Supabase schema and worker ADR, not in the PGXN 1.1.0 packaged SQL.
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.
Dependency and Source Caveats
- Enable
ltreeandpgmqbeforefsm_core; account forpg_jsonschemabecause upstream Supabase setup and Pigsty package dependencies list it, even though the PGXN control file only declaresltree, pgmq. pgmqqueues andfsm_dispatch_queuerows are part of the async execution model, so queue names, retention, and scheduler cleanup should be operated like application data.- The upstream repo has no release tag for
1.1.0or1.1.3; the authoritative packaged source for PGXN ispackages/database-src/pgxn-dist. - The
packages/database-src-extensionRust/pgrx tree is exploratory and marked not currently used. Do not treat it as the active extension implementation. - Public docs are sparse compared with the SQL surface. Treat unlisted helper functions as internal unless the SQL definition, Supabase migration, or worker ADR demonstrates their role.