What changed
PGX, Inc. announced pg_plan_filter 1.0.0 on October 7, 2026. The PostgreSQL loadable module checks a statement's estimated execution plan cost before allowing it to run. Administrators can set `plan_filter.statement_cost_limit` to reject a single expensive plan, `plan_filter.transaction_cost_limit` to cap the sum of estimated costs within one transaction, and `plan_filter.filter_select_only` to scope filtering to SELECT. Both limits default to zero (disabled). The module supports PostgreSQL 14 through 18 and can be loaded with `shared_preload_libraries`. Its upstream README documents important limits: estimates can be inaccurate, DDL without plans is not counted, and users who can alter planner cost settings can artificially lower estimates and evade the limits.
Why it matters
Small teams often discover an unexpectedly expensive query only after it slows the entire database. An application report, ORM-generated query or batch of individually modest statements can consume disproportionate capacity. pg_plan_filter adds a configurable refusal point before execution, including a cumulative transaction budget rather than only a timeout. That is a useful safety layer for cooperative workloads and self-hosted PostgreSQL, but it is not a billing cap, an actual resource meter or a defence against an adversarial SQL user. Its most important operational design decision is whether the workload trusts the session's planner settings.
Two budgets address different failure patterns
`statement_cost_limit` rejects one plan whose estimated cost exceeds the configured value. `transaction_cost_limit` adds estimated costs across executed statements in the same transaction, including repeated prepared-statement executions, so a batch of cheap-looking statements cannot grow indefinitely without tripping a cumulative threshold. The extension returns SQLSTATE `54001` on rejection, which applications can handle deliberately rather than treating every rejection as a generic database outage.
It measures the planner, not CPU seconds
PostgreSQL's cost units are planner estimates, not elapsed time, bytes scanned or money spent. A poorly estimated query may slip through; an efficient query may be refused. Operators should tune limits against real `EXPLAIN` plans and workload traces and expect false positives. Plain `EXPLAIN` can itself be affected by a nonzero statement limit unless the setting is temporarily disabled by an authorized user.
Do not mistake the module for a security boundary
The module's own maintainers explicitly warn that planner cost coefficients such as `seq_page_cost` and `cpu_tuple_cost` are session-settable. A user able to issue `SET` can lower those coefficients, even to zero, and make a dangerous plan appear cheap without permission to change the filter's superuser-only thresholds. Treat the filter as a guard against accidents or careless workloads, not a defence against malicious roles. Keep application-level rate limits, query privileges and infrastructure limits in place.
Deployment is an operator task
pg_plan_filter is a loadable module, not a normal `CREATE EXTENSION` installable package. The project recommends `shared_preload_libraries` for production and supports PostgreSQL 14–18. Administrators can apply different limits per role, keep privileged maintenance accounts unrestricted and test rejection handling before rolling it into an application. Most DDL without an execution plan is outside the budget.