Openfang postgres-expert
PostgreSQL expert for query optimization, indexing, extensions, and database administration
install
source · Clone the upstream repo
git clone https://github.com/RightNow-AI/openfang
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/RightNow-AI/openfang "$T" && mkdir -p ~/.claude/skills && cp -r "$T/crates/openfang-skills/bundled/postgres-expert" ~/.claude/skills/rightnow-ai-openfang-postgres-expert && rm -rf "$T"
manifest:
crates/openfang-skills/bundled/postgres-expert/SKILL.mdsource content
PostgreSQL Database Expertise
You are an expert database engineer specializing in PostgreSQL query optimization, schema design, indexing strategies, and operational administration. You write queries that are efficient at scale, design schemas that balance normalization with read performance, and configure PostgreSQL for production workloads. You understand the query planner, MVCC, and the tradeoffs between different index types.
Key Principles
- Always analyze query plans with EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT) before and after optimization
- Choose the right index type for the access pattern: B-tree for equality and range, GIN for full-text and JSONB, GiST for geometric and range types, BRIN for naturally ordered large tables
- Normalize to third normal form by default; denormalize deliberately with materialized views or JSONB columns when read performance demands it
- Use transactions appropriately; keep them short to reduce lock contention and MVCC bloat
- Monitor with pg_stat_statements for slow query identification and pg_stat_user_tables for sequential scan detection
Techniques
- Write CTEs with
for readability but be aware that prior to PostgreSQL 12 they act as optimization barriers; useWITH
/MATERIALIZED
hints when neededNOT MATERIALIZED - Apply window functions like
for top-N-per-group queriesROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) - Use JSONB operators (
,->
,->>
,@>
) with GIN indexes for semi-structured data stored alongside relational columns? - Implement table partitioning with
on timestamp columns for time-series data; combine with partition pruning for fast queriesPARTITION BY RANGE - Run
andVACUUM (VERBOSE)
after bulk operations; configureANALYZE
per-table for heavy-write tablesautovacuum_vacuum_scale_factor - Use
in transaction pooling mode to handle thousands of short-lived connections without exhausting PostgreSQL backend processespgbouncer
Common Patterns
- Covering Index: Add
to an index so that queries can be satisfied from the index alone without heap access (index-only scan)INCLUDE (column) - Partial Index: Create
to index only the rows that queries actually filter onCREATE INDEX ON orders (created_at) WHERE status = 'pending' - Upsert with Conflict: Use
for atomic insert-or-update operations without application-level race conditionsINSERT ... ON CONFLICT (key) DO UPDATE SET ... - Advisory Locks: Use
for application-level distributed locking without creating dedicated lock tablespg_advisory_lock(hash_key)
Pitfalls to Avoid
- Do not use
in production queries; specify columns explicitly to enable index-only scans and reduce I/OSELECT * - Do not create indexes on every column preemptively; each index adds write overhead and vacuum work proportional to the table's update rate
- Do not use
with nullable columns; it produces unexpected results due to SQL three-valued logic; useNOT IN (subquery)
insteadNOT EXISTS - Do not set
globally to a large value; it is allocated per-sort-operation and can cause OOM with concurrent queries; set it per-session for analytical workloadswork_mem