postgresql
Installation
SKILL.md
PostgreSQL
Overview
PostgreSQL is an open-source relational database with features that often replace separate tools: JSONB for semi-structured data, built-in full-text search, window functions, recursive CTEs, row-level security (RLS) for tenant isolation, and streaming replication. It offers partitioning and several index types (B-tree, GIN, GiST, BRIN). The current major version is 18 (18.6 as of August 2026); 14 reaches end of life on 12 November 2026, so new projects should start on 17 or 18.
Instructions
- Schemas: use
uuidprimary keys withDEFAULT gen_random_uuid()(built in since 13, no extension needed), oruuidv7()on 18+ when you want time-ordered keys that keep B-tree inserts local. Usetimestamptzfor all timestamps,textrather thanvarchar(n)unless a limit is a real rule,GENERATED ALWAYS AS IDENTITYfor integer keys, and CHECK, UNIQUE and foreign keys with explicitON DELETE. Partition large time-series tables withPARTITION BY RANGE. - JSON: use
jsonbfor genuinely dynamic data and a GIN index for containment (@>) queries; keep known fields in real columns. - Indexing: read
EXPLAIN (ANALYZE, BUFFERS)output before adding an index. Use partial indexes for filtered queries, expression indexes for computed values, andINCLUDEcolumns for index-only scans. Build on live tables withCREATE INDEX CONCURRENTLY. - Full-text search: add a
tsvectorcolumn declaredGENERATED ALWAYS AS (...) STOREDwith a GIN index. Always pass the language config explicitly (to_tsvector('english', ...)), wrap nullable columns incoalesce, query withwebsearch_to_tsquery(accepts quotes and-term, never raises syntax errors) and rank withts_rank. - Multi-tenancy: enable RLS and write policies with
USINGandWITH CHECK. Table owners, superusers and roles withBYPASSRLSskip policies, so connect the application as a separate non-owner role (or addFORCE ROW LEVEL SECURITY). Pass the tenant withset_config('app.tenant_id', $1, true)inside the transaction. - Operations: pool connections (PgBouncer, or the pooler your platform provides) because each connection is a server process; enable
pg_stat_statementsthroughshared_preload_librariesfollowed byCREATE EXTENSION pg_stat_statements; rely on autovacuum and runANALYZEby hand after bulk loads; use Patroni or a managed service for failover.