Postgresql Code Review
GitHubOfficialOriginally contributed by @shubham070 as prompts/postgresql-code-review.prompt.md; moved into a skill by pull request #761Distributed by GitHub
- Skill
- Review and audit
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The PostgreSQL Code Review Assistant provides expert-level analysis of SQL code, specifically targeting PostgreSQL-native features and best practices. It helps developers move beyond generic SQL patterns to leverage PostgreSQL's advanced capabilities, such as JSONB, custom types, GIN/GiST indexing, and Row Level Security. The assistant identifies anti-patterns, suggests performance optimizations, and ensures schema designs align with PostgreSQL-specific quality standards.
What it does
- Reviews schema design for optimal use of PostgreSQL types like JSONB, CITEXT, and ENUMs.
- Identifies performance bottlenecks in JSONB and array operations.
- Suggests appropriate indexing strategies including GIN and GiST.
- Audits PL/pgSQL functions and triggers for efficiency and best practices.
- Validates the implementation of Row Level Security (RLS) and granular privilege management.
- Checks for proper usage of PostgreSQL extensions like pgcrypto and uuid-ossp.
When to use it
- During the code review phase of database schema migrations.
- When optimizing slow-running queries involving JSONB or arrays.
- When implementing security policies or RLS in a PostgreSQL environment.
- Before finalizing custom types, domains, or complex trigger functions.
- To ensure database code follows PostgreSQL-specific performance and security standards.
Advantages
- Promotes the use of PostgreSQL-native features over generic SQL workarounds.
- Improves query performance through specialized indexing and operator usage.
- Enhances data integrity via custom domains and CHECK constraints.
- Strengthens database security through expert-guided RLS implementation.
- Reduces technical debt by identifying PostgreSQL-specific anti-patterns.
Usage examples
- “Review this table schema for PostgreSQL best practices: CREATE TABLE orders (data TEXT);”
- The assistant would suggest changing the data type to JSONB for better performance and indexing, and recommend adding CHECK constraints for data validation.
- “Audit this trigger function for performance issues.”
- The assistant would analyze the trigger logic, suggest using CURRENT_TIMESTAMP instead of NOW(), and recommend adding a WHEN clause to prevent unnecessary execution.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/github/postgresql-code-review/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip postgresql-code-review.zip -d .agents/skills
Documentation by shubham070
PostgreSQL Code Review Assistant
Expert PostgreSQL code review for ${selection} (or entire project if no selection). Focus on PostgreSQL-specific best practices, anti-patterns, and quality standards that are unique to PostgreSQL.
🎯 PostgreSQL-Specific Review Areas
JSONB Best Practices
-- ❌ BAD: Inefficient JSONB usage
SELECT * FROM orders WHERE data->>'status' = 'shipped'; -- No index support
-- ✅ GOOD: Indexable JSONB queries
CREATE INDEX idx_orders_status ON orders USING gin((data->'status'));
SELECT * FROM orders WHERE data @> '{"status": "shipped"}';
-- ❌ BAD: Deep nesting without consideration
UPDATE orders SET data = data || '{"shipping":{"tracking":{"number":"123"}}}';
-- ✅ GOOD: Structured JSONB with validation
ALTER TABLE orders ADD CONSTRAINT valid_status
CHECK (data->>'status' IN ('pending', 'shipped', 'delivered'));Array Operations Review
-- ❌ BAD: Inefficient array operations
SELECT * FROM products WHERE 'electronics' = ANY(categories); -- No index
-- ✅ GOOD: GIN indexed array queries
CREATE INDEX idx_products_categories ON products USING gin(categories);
SELECT * FROM products WHERE categories @> ARRAY['electronics'];
-- ❌ BAD: Array concatenation in loops
-- This would be inefficient in a function/procedure
-- ✅ GOOD: Bulk array operations
UPDATE products SET categories = categories || ARRAY['new_category']
WHERE id IN (SELECT id FROM products WHERE condition);PostgreSQL Schema Design Review
-- ❌ BAD: Not using PostgreSQL features
CREATE TABLE users (
id INTEGER,
email VARCHAR(255),
created_at TIMESTAMP
);
-- ✅ GOOD: PostgreSQL-optimized schema
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email CITEXT UNIQUE NOT NULL, -- Case-insensitive email
created_at TIMESTAMPTZ DEFAULT NOW(),
metadata JSONB DEFAULT '{}',
CONSTRAINT valid_email CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')
);
-- Add JSONB GIN index for metadata queries
CREATE INDEX idx_users_metadata ON users USING gin(metadata);Custom Types and Domains
-- ❌ BAD: Using generic types for specific data
CREATE TABLE transactions (
amount DECIMAL(10,2),
currency VARCHAR(3),
status VARCHAR(20)
);
-- ✅ GOOD: PostgreSQL custom types
CREATE TYPE currency_code AS ENUM ('USD', 'EUR', 'GBP', 'JPY');
CREATE TYPE transaction_status AS ENUM ('pending', 'completed', 'failed', 'cancelled');
CREATE DOMAIN positive_amount AS DECIMAL(10,2) CHECK (VALUE > 0);
CREATE TABLE transactions (
amount positive_amount NOT NULL,
currency currency_code NOT NULL,
status transaction_status DEFAULT 'pending'
);🔍 PostgreSQL-Specific Anti-Patterns
Performance Anti-Patterns
Avoiding PostgreSQL-specific indexes: Not using GIN/GiST for appropriate data types
Misusing JSONB: Treating JSONB like a simple string field
Ignoring array operators: Using inefficient array operations
Poor partition key selection: Not leveraging PostgreSQL partitioning effectively
Schema Design Issues
Not using ENUM types: Using VARCHAR for limited value sets
Ignoring constraints: Missing CHECK constraints for data validation
Wrong data types: Using VARCHAR instead of TEXT or CITEXT
Missing JSONB structure: Unstructured JSONB without validation
Function and Trigger Issues
-- ❌ BAD: Inefficient trigger function
CREATE OR REPLACE FUNCTION update_modified_time()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW(); -- Should use TIMESTAMPTZ
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- ✅ GOOD: Optimized trigger function
CREATE OR REPLACE FUNCTION update_modified_time()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Set trigger to fire only when needed
CREATE TRIGGER update_modified_time_trigger
BEFORE UPDATE ON table_name
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE FUNCTION update_modified_time();📊 PostgreSQL Extension Usage Review
Extension Best Practices
-- ✅ Check if extension exists before creating
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- ✅ Use extensions appropriately
-- UUID generation
SELECT uuid_generate_v4();
-- Password hashing
SELECT crypt('password', gen_salt('bf'));
-- Fuzzy text matching
SELECT word_similarity('postgres', 'postgre');🛡️ PostgreSQL Security Review
Row Level Security (RLS)
-- ✅ GOOD: Implementing RLS
ALTER TABLE sensitive_data ENABLE ROW LEVEL SECURITY;
CREATE POLICY user_data_policy ON sensitive_data
FOR ALL TO application_role
USING (user_id = current_setting('app.current_user_id')::INTEGER);Privilege Management
-- ❌ BAD: Overly broad permissions
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO app_user;
-- ✅ GOOD: Granular permissions
GRANT SELECT, INSERT, UPDATE ON specific_table TO app_user;
GRANT USAGE ON SEQUENCE specific_table_id_seq TO app_user;🎯 PostgreSQL Code Quality Checklist
Schema Design
[ ] Using appropriate PostgreSQL data types (CITEXT, JSONB, arrays)
[ ] Leveraging ENUM types for constrained values
[ ] Implementing proper CHECK constraints
[ ] Using TIMESTAMPTZ instead of TIMESTAMP
[ ] Defining custom domains for reusable constraints
Performance Considerations
[ ] Appropriate index types (GIN for JSONB/arrays, GiST for ranges)
[ ] JSONB queries using containment operators (@>, ?)
[ ] Array operations using PostgreSQL-specific operators
[ ] Proper use of window functions and CTEs
[ ] Efficient use of PostgreSQL-specific functions
PostgreSQL Features Utilization
[ ] Using extensions where appropriate
[ ] Implementing stored procedures in PL/pgSQL when beneficial
[ ] Leveraging PostgreSQL's advanced SQL features
[ ] Using PostgreSQL-specific optimization techniques
[ ] Implementing proper error handling in functions
Security and Compliance
[ ] Row Level Security (RLS) implementation where needed
[ ] Proper role and privilege management
[ ] Using PostgreSQL's built-in encryption functions
[ ] Implementing audit trails with PostgreSQL features
📝 PostgreSQL-Specific Review Guidelines
Data Type Optimization: Ensure PostgreSQL-specific types are used appropriately
Index Strategy: Review index types and ensure PostgreSQL-specific indexes are utilized
JSONB Structure: Validate JSONB schema design and query patterns
Function Quality: Review PL/pgSQL functions for efficiency and best practices
Extension Usage: Verify appropriate use of PostgreSQL extensions
Performance Features: Check utilization of PostgreSQL's advanced features
Security Implementation: Review PostgreSQL-specific security features
Focus on PostgreSQL's unique capabilities and ensure the code leverages what makes PostgreSQL special rather than treating it as a generic SQL database.
Files
- ATTRIBUTION.mdAdded by AutoGineer1.1 KiB
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md7.3 KiB
SKILL.md
PostgreSQL Code Review Assistant
Expert PostgreSQL code review for ${selection} (or entire project if no selection). Focus on PostgreSQL-specific best practices, anti-patterns, and quality standards that are unique to PostgreSQL.
🎯 PostgreSQL-Specific Review Areas
JSONB Best Practices
-- ❌ BAD: Inefficient JSONB usage
SELECT * FROM orders WHERE data->>'status' = 'shipped'; -- No index support
-- ✅ GOOD: Indexable JSONB queries
CREATE INDEX idx_orders_status ON orders USING gin((data->'status'));
SELECT * FROM orders WHERE data @> '{"status": "shipped"}';
-- ❌ BAD: Deep nesting without consideration
UPDATE orders SET data = data || '{"shipping":{"tracking":{"number":"123"}}}';
-- ✅ GOOD: Structured JSONB with validation
ALTER TABLE orders ADD CONSTRAINT valid_status
CHECK (data->>'status' IN ('pending', 'shipped', 'delivered'));Array Operations Review
-- ❌ BAD: Inefficient array operations
SELECT * FROM products WHERE 'electronics' = ANY(categories); -- No index
-- ✅ GOOD: GIN indexed array queries
CREATE INDEX idx_products_categories ON products USING gin(categories);
SELECT * FROM products WHERE categories @> ARRAY['electronics'];
-- ❌ BAD: Array concatenation in loops
-- This would be inefficient in a function/procedure
-- ✅ GOOD: Bulk array operations
UPDATE products SET categories = categories || ARRAY['new_category']
WHERE id IN (SELECT id FROM products WHERE condition);PostgreSQL Schema Design Review
-- ❌ BAD: Not using PostgreSQL features
CREATE TABLE users (
id INTEGER,
email VARCHAR(255),
created_at TIMESTAMP
);
-- ✅ GOOD: PostgreSQL-optimized schema
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email CITEXT UNIQUE NOT NULL, -- Case-insensitive email
created_at TIMESTAMPTZ DEFAULT NOW(),
metadata JSONB DEFAULT '{}',
CONSTRAINT valid_email CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')
);
-- Add JSONB GIN index for metadata queries
CREATE INDEX idx_users_metadata ON users USING gin(metadata);Custom Types and Domains
-- ❌ BAD: Using generic types for specific data
CREATE TABLE transactions (
amount DECIMAL(10,2),
currency VARCHAR(3),
status VARCHAR(20)
);
-- ✅ GOOD: PostgreSQL custom types
CREATE TYPE currency_code AS ENUM ('USD', 'EUR', 'GBP', 'JPY');
CREATE TYPE transaction_status AS ENUM ('pending', 'completed', 'failed', 'cancelled');
CREATE DOMAIN positive_amount AS DECIMAL(10,2) CHECK (VALUE > 0);
CREATE TABLE transactions (
amount positive_amount NOT NULL,
currency currency_code NOT NULL,
status transaction_status DEFAULT 'pending'
);🔍 PostgreSQL-Specific Anti-Patterns
Performance Anti-Patterns
Avoiding PostgreSQL-specific indexes: Not using GIN/GiST for appropriate data types
Misusing JSONB: Treating JSONB like a simple string field
Ignoring array operators: Using inefficient array operations
Poor partition key selection: Not leveraging PostgreSQL partitioning effectively
Schema Design Issues
Not using ENUM types: Using VARCHAR for limited value sets
Ignoring constraints: Missing CHECK constraints for data validation
Wrong data types: Using VARCHAR instead of TEXT or CITEXT
Missing JSONB structure: Unstructured JSONB without validation
Function and Trigger Issues
-- ❌ BAD: Inefficient trigger function
CREATE OR REPLACE FUNCTION update_modified_time()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW(); -- Should use TIMESTAMPTZ
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- ✅ GOOD: Optimized trigger function
CREATE OR REPLACE FUNCTION update_modified_time()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Set trigger to fire only when needed
CREATE TRIGGER update_modified_time_trigger
BEFORE UPDATE ON table_name
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE FUNCTION update_modified_time();📊 PostgreSQL Extension Usage Review
Extension Best Practices
-- ✅ Check if extension exists before creating
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- ✅ Use extensions appropriately
-- UUID generation
SELECT uuid_generate_v4();
-- Password hashing
SELECT crypt('password', gen_salt('bf'));
-- Fuzzy text matching
SELECT word_similarity('postgres', 'postgre');🛡️ PostgreSQL Security Review
Row Level Security (RLS)
-- ✅ GOOD: Implementing RLS
ALTER TABLE sensitive_data ENABLE ROW LEVEL SECURITY;
CREATE POLICY user_data_policy ON sensitive_data
FOR ALL TO application_role
USING (user_id = current_setting('app.current_user_id')::INTEGER);Privilege Management
-- ❌ BAD: Overly broad permissions
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO app_user;
-- ✅ GOOD: Granular permissions
GRANT SELECT, INSERT, UPDATE ON specific_table TO app_user;
GRANT USAGE ON SEQUENCE specific_table_id_seq TO app_user;🎯 PostgreSQL Code Quality Checklist
Schema Design
[ ] Using appropriate PostgreSQL data types (CITEXT, JSONB, arrays)
[ ] Leveraging ENUM types for constrained values
[ ] Implementing proper CHECK constraints
[ ] Using TIMESTAMPTZ instead of TIMESTAMP
[ ] Defining custom domains for reusable constraints
Performance Considerations
[ ] Appropriate index types (GIN for JSONB/arrays, GiST for ranges)
[ ] JSONB queries using containment operators (@>, ?)
[ ] Array operations using PostgreSQL-specific operators
[ ] Proper use of window functions and CTEs
[ ] Efficient use of PostgreSQL-specific functions
PostgreSQL Features Utilization
[ ] Using extensions where appropriate
[ ] Implementing stored procedures in PL/pgSQL when beneficial
[ ] Leveraging PostgreSQL's advanced SQL features
[ ] Using PostgreSQL-specific optimization techniques
[ ] Implementing proper error handling in functions
Security and Compliance
[ ] Row Level Security (RLS) implementation where needed
[ ] Proper role and privilege management
[ ] Using PostgreSQL's built-in encryption functions
[ ] Implementing audit trails with PostgreSQL features
📝 PostgreSQL-Specific Review Guidelines
Data Type Optimization: Ensure PostgreSQL-specific types are used appropriately
Index Strategy: Review index types and ensure PostgreSQL-specific indexes are utilized
JSONB Structure: Validate JSONB schema design and query patterns
Function Quality: Review PL/pgSQL functions for efficiency and best practices
Extension Usage: Verify appropriate use of PostgreSQL extensions
Performance Features: Check utilization of PostgreSQL's advanced features
Security Implementation: Review PostgreSQL-specific security features
Focus on PostgreSQL's unique capabilities and ensure the code leverages what makes PostgreSQL special rather than treating it as a generic SQL database.
Requirements and compatibility
Written for: GitHub Copilot
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Originally contributed by
@shubham070as prompts/postgresql-code-review.prompt.mdmoved into a skill by pull request #761
- Publisher
- GitHub (Official)
- Distributed by
- GitHub
- Source
- github/awesome-copilot · skills/postgresql-code-review · commit 797337f
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Contributors
- CypherHK, derekclair, shubham070
AutoGineer is not affiliated with or endorsed by shubham070 or GitHub.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download postgresql-code-review.zip