Rules#
What are Rules in PostgreSQL?#
In PostgreSQL, a Rule is:
A query-rewrite mechanism
PostgreSQL rewrites your SQL before execution.
- Important:
Rules run before triggers
They rewrite the query itself
They are not procedural logic
- Think of Rules as:
βWhen the user runs THIS query, secretly replace it with THAT query.β
Where Rules sit in the stack
Execution order:
SQL statement
β
RULE SYSTEM (query rewrite)
β
RLS policies
β
Triggers
β
Actual execution
Rules happen very early.
Why Rules exist (historical context)#
- Rules were created originally to:
Implement views
Redirect writes to views
Support early updatable views
- Today:
Mostly used internally
Rarely recommended for application logic
Basic Rule example (SELECT rewrite)
Suppose you want:
SELECT * FROM students;
To secretly become:
SELECT * FROM students WHERE active = true;
You can do:
CREATE RULE students_only_active AS
ON SELECT TO students
DO INSTEAD
SELECT * FROM students WHERE active = true;
Now:
SELECT * FROM students;
returns only active students.
DO INSTEAD vs DO ALSO#
- DO INSTEAD
Replaces the original query
- DO ALSO
Runs in addition to the original query
Example:
CREATE RULE log_student_insert AS
ON INSERT TO students
DO ALSO
INSERT INTO student_logs(student_id, action)
VALUES (NEW.id, 'insert');
Rules with INSERT (redirect writes)
Classic use case: updatable views
CREATE VIEW students_public AS
SELECT id, name FROM students;
Now allow inserts into the view:
CREATE RULE students_public_insert AS
ON INSERT TO students_public
DO INSTEAD
INSERT INTO students (name)
VALUES (NEW.name);
This is how PostgreSQL made views βwritableβ before triggers existed.
Rules vs Triggers (VERY IMPORTANT)
Feature |
Rules |
Triggers |
|---|---|---|
Timing |
Before execution |
During execution |
Behavior |
Rewrite query |
Run procedural code |
Row-level |
β No |
β Yes |
Predictable |
β Hard |
β Clear |
Modern usage |
β οΈ Rare |
β Standard |
99% of the time, you want triggers, not rules
Rules vs RLS
Feature |
Rules |
RLS |
|---|---|---|
Purpose |
Rewrite queries |
Enforce security |
Security |
β Unsafe |
β Strong |
Row visibility |
β Indirect |
β Guaranteed |
Recommended |
β No |
β Yes |
Rules do not replace RLS.
Why Rules are dangerous#
1. They are invisible
SELECT * FROM students;
You cannot tell what rule rewrote it.
- Hard to debug
EXPLAIN may not show intent clearly
Complex rewrite chains
3. Can break expectations
Multiple rules can fire and interact unexpectedly.
When Rules are acceptable
β Internal PostgreSQL features
β Very simple, read-only views
β Legacy systems
β Business logic
β Security
β Auditing
β Multi-tenant filtering
PostgreSQLβs own recommendation
- PostgreSQL documentation clearly implies:
Use triggers instead of rules for most tasks.
pgAdmin: What youβre seeing
In your tree:
students
βββ Rules
- This folder exists because:
PostgreSQL supports rules
But most tables have zero rules
Thatβs normal.
Rule lifecycle
-- create
CREATE RULE ...
-- view
SELECT * FROM pg_rules WHERE tablename = 'students';
-- drop
DROP RULE rule_name ON students;
Mental model (remember this)
Rules rewrite SQL text
Triggers react to data changes
- If you need:
Logic β Trigger
Security β RLS
Aggregation β View / Materialized View
API β RLS + functions
Final guidance (important)
- For modern PostgreSQL systems:
β Avoid Rules
β Use Triggers
β Use RLS
β Use Views (read-only)
β Use Materialized Views for performance