Turn changing PostgreSQL facts into durable, inspectable policy state and work.
pg-react is a PostgreSQL-native rule and policy engine. Conditions are ordinary relations or views; declarations are typed SQL values; lifecycle, decisions, work, attempts, and explanations remain queryable in PostgreSQL.
M54 / extension 0.43.1 is the current release. It keeps the package workflow
and adds one ordinary path for creating, reviewing, replacing, exporting, and
recovering rules and decisions. 1.0.0 is postponed indefinitely. Start with the
documentation home.
| Audience | Start here | Main question |
|---|---|---|
| Application developer | Getting Started | How do I define and deploy a first rule? |
| PostgreSQL developer | Order review showcase | How do facts, views, consequences, and durable work fit together? |
| Operator | Operations | How do I inspect, retry, pause, replace, and remove work? |
| Reviewer or architect | Explain an Outcome, Concepts, and Changing Policies Safely | What happened, what changed, and where are the boundaries? |
authoritative PostgreSQL facts
|
v
condition relation
|
v
lifecycle / decision
|
v
durable work
This constraint rule records the high-risk orders that currently require review:
CREATE VIEW rule_def.high_value_risky_order AS
SELECT o.order_id, o.customer_id, o.amount
FROM app.orders AS o
WHERE o.risk_level = 'HIGH'
AND o.amount > 10000;
SELECT pgreact.validate(pgreact.rule(
name => 'manual-review-required',
condition => 'rule_def.high_value_risky_order'::regclass,
semantic_key => 'order_id'::name
));
SELECT pgreact.preview(pgreact.rule(
name => 'manual-review-required',
condition => 'rule_def.high_value_risky_order'::regclass,
semantic_key => 'order_id'::name
));
WITH proposal AS (
SELECT pgreact.rule(
name => 'manual-review-required',
condition => 'rule_def.high_value_risky_order'::regclass,
semantic_key => 'order_id'::name
) AS value
), review AS (
SELECT value, pgreact.preview(value) AS result FROM proposal
)
SELECT pgreact.deploy(value, pgreact.review_token(result)) FROM review;pgreact.rule() defaults to kind => 'CONSTRAINT'. A rule with
on_activate, on_change, or on_deactivate consequences must explicitly use
kind => 'COMMAND'. See Getting Started for the
complete managed-runtime workflow.
- Rules: stable semantic identity, current matches, activation generations, revisions, typed consequences, retries, and explanations.
- Decisions: candidate evaluation with explicit winner, ambiguity, and no-candidate states.
- Policy sets: versioned membership and relational applicability.
- Safe changes:
pgreact.compare()andpgreact.compare_results()compare current and proposed declarations over current authoritative facts without deploying or executing effects. - Why a result changed: add
{"why_changed": true}to a supported comparison, replay, or backtest call to receive bounded causes and public evidence. Leave it out to keep the earlier result unchanged. - Why a result is absent: add a
why_notobject topgreact.explainwhen you need a bounded answer for one expected rule match, decision result, or policy eligibility result. - Why a result exists: add
causal_pathto follow a bounded path from a decision or work item to public facts. Retain a complete path as an evidence snapshot when the answer must outlive current source evidence. See Explain an Outcome. - Advanced reasoning: installed public surfaces include maintained derived facts and logical support, bounded positive recursion, stratified negation and aggregation, shared conditions, temporal and effective-dated policies, parameter families, provenance, and decision analysis. These are advanced APIs, not required for the ordinary first-rule path.
PostgreSQL-managed workers are the normal runtime. One managed worker is
started for each configured database, polls on
pg_react.poll_interval_ms, coordinates maintenance, and drains eligible
work. The external pg-reactd program is a compatibility path; it can call
pgreact_api.run() and therefore can create work as well as drain it.
Comparison varies the declaration, not the facts:
current facts + deployed declaration
versus
current facts + proposed declaration
It reports bounded current, proposed, delta, lifecycle, and would-be
work evidence. M35 also accepts typed hypothetical inserts, updates, and
deletes for direct table sources. M36 replays caller-supplied history, and M37
backtests at most two policies over that history. Rule comparison is limited to
one bigint key even though separate advanced installed authoring APIs support
broader typed keys.
- PostgreSQL remains the authoritative fact store.
- Database consequences and their pg-react state changes use PostgreSQL transactions.
- External delivery is at least once; consumers must deduplicate.
- Private schemas and internal UUIDs are not part of the ordinary API.
- Comparison is bounded and may be
partial; it has no continuation token. - pg-react is not a synchronous write-path hook, a global-ordering service, a distributed transaction coordinator, or a general workflow/BPM engine.
The qualified 0.43.1 environment is PostgreSQL 18.3, pg_trickle 0.81.0,
pgrx 0.18.0, Linux amd64, READ COMMITTED, and the PostgreSQL-managed
runtime. See the Support Matrix before adopting it.
- Glossary
- Getting Started
- Order review showcase: a runnable PostgreSQL example covering rules, durable review work, routing decisions, retries, policy applicability, and side-effect-free comparison.
- Concepts
- Authoring Rules and Policies
- Changing Policies Safely
- Operations
- API Reference
- Known Limitations
Release and milestone evidence is available through History, not required for normal use.
The project is pg-react. PostgreSQL and Rust identifiers use underscores:
install pg_react and call the public pgreact or pgreact_api SQL surfaces.
Licensed under the Apache License 2.0.