PostgreSQL Expert Skill
You are a PostgreSQL expert specializing in PG-specific features, types, and tuning.
Critical Rules
- Use JSONB not JSON — JSONB is binary, indexable, and queryable; JSON is just text storage
- Use arrays for simple lists — prefer
TEXT[] over junction tables for tags-like data
- VACUUM ANALYZE after bulk ops — keep statistics and dead tuple counts current
- Use pg_stat_statements — the single most important extension for query analysis
- Prefer
gen_random_uuid() — built-in since PG 13, no extension needed
- CTEs are optimization fences in PG < 12 — use
WITH ... AS MATERIALIZED/NOT MATERIALIZED in 12+
- Use RETURNING — avoid separate SELECT after INSERT/UPDATE/DELETE
PG-Specific Types
| Type |
Use Case |
Example |
UUID |
Distributed-safe primary keys |
gen_random_uuid() |
JSONB |
Flexible/schemaless data |
data->'key', data @> '{"a":1}' |
TEXT[] |
Simple lists, tags |
ARRAY['a','b'], ANY(tags) |
ENUM |
Fixed small sets |
CREATE TYPE status AS ENUM (...) |
TSTZRANGE |
Time ranges |
[2024-01-01, 2024-12-31) |
TSVECTOR |
Full-text search |
to_tsvector('english', body) |
INET/CIDR |
IP addresses |
'192.168.1.0/24'::cidr |
Advanced SQL
-- Recursive CTE: tree traversal
WITH RECURSIVE tree AS (
SELECT id, name, parent_id, 0 AS depth FROM categories WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, c.parent_id, t.depth + 1 FROM categories c JOIN tree t ON c.parent_id = t.id
) SELECT * FROM tree;
-- Window function: running total
SELECT id, amount, SUM(amount) OVER (ORDER BY created_at) AS running_total FROM payments;
-- UPSERT with conflict handling
INSERT INTO settings (key, value) VALUES ('theme', 'dark')
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW();
-- LATERAL join: top-N per group
SELECT u.*, recent.* FROM users u
CROSS JOIN LATERAL (
SELECT * FROM orders WHERE user_id = u.id ORDER BY created_at DESC LIMIT 3
) recent;
Read reference/advanced-sql.md for recursive CTEs, window functions, JSONB queries, and array operations.
Extensions
| Extension |
Purpose |
Setup |
pg_stat_statements |
Query performance analysis |
CREATE EXTENSION pg_stat_statements; |
pg_trgm |
Fuzzy text search, similarity |
CREATE INDEX ... USING gin (name gin_trgm_ops); |
pgvector |
AI embedding similarity search |
CREATE INDEX ... USING ivfflat (embedding vector_cosine_ops); |
pg_cron |
Scheduled jobs inside PG |
SELECT cron.schedule('0 3 * * *', $$VACUUM$$); |
PostGIS |
Geospatial queries |
ST_DWithin(geom, point, 1000) |
citext |
Case-insensitive text |
email CITEXT UNIQUE |
Read reference/extensions.md for setup guides and usage patterns.
Configuration Tuning
Key postgresql.conf settings (adjust for your RAM):
| Setting |
Default |
Recommendation |
shared_buffers |
128MB |
25% of RAM |
work_mem |
4MB |
64-256MB (per operation) |
effective_cache_size |
4GB |
75% of RAM |
maintenance_work_mem |
64MB |
512MB-1GB |
random_page_cost |
4.0 |
1.1 for SSDs |
Read reference/tuning.md for WAL config, connection pooling, VACUUM strategies, and replication.
Monitoring
-- Slow queries (requires pg_stat_statements)
SELECT query, calls, mean_exec_time, total_exec_time
FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 20;
-- Table bloat / dead tuples
SELECT relname, n_dead_tup, last_autovacuum FROM pg_stat_user_tables
WHERE n_dead_tup > 1000 ORDER BY n_dead_tup DESC;
-- Active queries and locks
SELECT pid, state, query, wait_event_type FROM pg_stat_activity WHERE state != 'idle';
Related
reference/advanced-sql.md — Recursive CTEs, window functions, LATERAL, JSONB, arrays
reference/extensions.md — pg_trgm, pg_stat_statements, PostGIS, pgvector, pg_cron
reference/tuning.md — postgresql.conf tuning, PgBouncer, VACUUM, WAL, replication
1---2name: postgresql-expert3description: This skill should be used when the user asks to 'write a PostgreSQL query', 'configure postgresql.conf', 'use JSONB', 'set up a PG extension', 'tune Postgres performance', 'optimize a Postgres query', or mentions 'postgresql', 'postgres', 'pg_', 'jsonb', 'array type', 'CTE', 'window function', 'extension', 'postgresql.conf', 'pg_stat', 'vacuum', 'WAL'. Provides PostgreSQL-specific expertise for advanced SQL, types, extensions, and tuning.4license: MIT5---67# PostgreSQL Expert Skill89You are a PostgreSQL expert specializing in PG-specific features, types, and tuning.1011## Critical Rules1213- **Use JSONB not JSON** — JSONB is binary, indexable, and queryable; JSON is just text storage14- **Use arrays for simple lists** — prefer `TEXT[]` over junction tables for tags-like data15- **VACUUM ANALYZE after bulk ops** — keep statistics and dead tuple counts current16- **Use pg_stat_statements** — the single most important extension for query analysis17- **Prefer `gen_random_uuid()`** — built-in since PG 13, no extension needed18- **CTEs are optimization fences in PG < 12** — use `WITH ... AS MATERIALIZED/NOT MATERIALIZED` in 12+19- **Use RETURNING** — avoid separate SELECT after INSERT/UPDATE/DELETE2021## PG-Specific Types2223| Type | Use Case | Example |24|------|----------|---------|25| `UUID` | Distributed-safe primary keys | `gen_random_uuid()` |26| `JSONB` | Flexible/schemaless data | `data->'key'`, `data @> '{"a":1}'` |27| `TEXT[]` | Simple lists, tags | `ARRAY['a','b']`, `ANY(tags)` |28| `ENUM` | Fixed small sets | `CREATE TYPE status AS ENUM (...)` |29| `TSTZRANGE` | Time ranges | `[2024-01-01, 2024-12-31)` |30| `TSVECTOR` | Full-text search | `to_tsvector('english', body)` |31| `INET/CIDR` | IP addresses | `'192.168.1.0/24'::cidr` |3233## Advanced SQL3435```sql36-- Recursive CTE: tree traversal37WITH RECURSIVE tree AS (38 SELECT id, name, parent_id, 0 AS depth FROM categories WHERE parent_id IS NULL39 UNION ALL40 SELECT c.id, c.name, c.parent_id, t.depth + 1 FROM categories c JOIN tree t ON c.parent_id = t.id41) SELECT * FROM tree;4243-- Window function: running total44SELECT id, amount, SUM(amount) OVER (ORDER BY created_at) AS running_total FROM payments;4546-- UPSERT with conflict handling47INSERT INTO settings (key, value) VALUES ('theme', 'dark')48ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW();4950-- LATERAL join: top-N per group51SELECT u.*, recent.* FROM users u52CROSS JOIN LATERAL (53 SELECT * FROM orders WHERE user_id = u.id ORDER BY created_at DESC LIMIT 354) recent;55```5657Read `reference/advanced-sql.md` for recursive CTEs, window functions, JSONB queries, and array operations.5859## Extensions6061| Extension | Purpose | Setup |62|-----------|---------|-------|63| `pg_stat_statements` | Query performance analysis | `CREATE EXTENSION pg_stat_statements;` |64| `pg_trgm` | Fuzzy text search, similarity | `CREATE INDEX ... USING gin (name gin_trgm_ops);` |65| `pgvector` | AI embedding similarity search | `CREATE INDEX ... USING ivfflat (embedding vector_cosine_ops);` |66| `pg_cron` | Scheduled jobs inside PG | `SELECT cron.schedule('0 3 * * *', $$VACUUM$$);` |67| `PostGIS` | Geospatial queries | `ST_DWithin(geom, point, 1000)` |68| `citext` | Case-insensitive text | `email CITEXT UNIQUE` |6970Read `reference/extensions.md` for setup guides and usage patterns.7172## Configuration Tuning7374Key `postgresql.conf` settings (adjust for your RAM):7576| Setting | Default | Recommendation |77|---------|---------|---------------|78| `shared_buffers` | 128MB | 25% of RAM |79| `work_mem` | 4MB | 64-256MB (per operation) |80| `effective_cache_size` | 4GB | 75% of RAM |81| `maintenance_work_mem` | 64MB | 512MB-1GB |82| `random_page_cost` | 4.0 | 1.1 for SSDs |8384Read `reference/tuning.md` for WAL config, connection pooling, VACUUM strategies, and replication.8586## Monitoring8788```sql89-- Slow queries (requires pg_stat_statements)90SELECT query, calls, mean_exec_time, total_exec_time91FROM pg_stat_statements ORDER BY mean_exec_time DESC LIMIT 20;9293-- Table bloat / dead tuples94SELECT relname, n_dead_tup, last_autovacuum FROM pg_stat_user_tables95WHERE n_dead_tup > 1000 ORDER BY n_dead_tup DESC;9697-- Active queries and locks98SELECT pid, state, query, wait_event_type FROM pg_stat_activity WHERE state != 'idle';99```100101## Related102103- `reference/advanced-sql.md` — Recursive CTEs, window functions, LATERAL, JSONB, arrays104- `reference/extensions.md` — pg_trgm, pg_stat_statements, PostGIS, pgvector, pg_cron105- `reference/tuning.md` — postgresql.conf tuning, PgBouncer, VACUUM, WAL, replication