Back to skills
SKILL.md
Coding Pg
ASecurityOwns PostgreSQL work: schema and DDL, migrations and lock levels, set-algebraic queries, functions and PL/pgSQL, indexes, RLS and tenant isolation, extensions (pgvector, PostGIS, TimescaleDB, pg_partman, pg_cron, pg_duckdb), logical replication and CDC, server tuning (vacuum, WAL, parallel query, JIT), EXPLAIN plans, wait-event and lock-contention diagnosis, and SQL embedded in TypeScript through @effect/sql-pg. Use when authoring, reviewing, migrating, or debugging any .sql file or SQL strin...
- 2 stars
- 0 votes
- 0 copies
- 1 view
- Added September 20, 2026
Works with
Security analysis
100/100Pro scans all 12 files and shows the line behind each finding
npx -y skills add bsamiee/Parametric_Forge --skill coding-pg --agent claude-codeAre you the author of Coding Pg?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/bsamiee-coding-pg-parametric-forge)---
name: coding-pg
description: >-
Owns PostgreSQL work: schema and DDL, migrations and lock levels, set-algebraic
queries, functions and PL/pgSQL, indexes, RLS and tenant isolation, extensions (pgvector,
PostGIS, TimescaleDB, pg_partman, pg_cron, pg_duckdb), logical replication and CDC, server
tuning (vacuum, WAL, parallel query, JIT), EXPLAIN plans, wait-event and lock-contention
diagnosis, and SQL embedded in TypeScript through @effect/sql-pg. Use when authoring,
reviewing, migrating, or debugging any .sql file or SQL string and "lint my SQL".
Provisioning and hosting a database instance belongs to pulumi.
---
# [CODING_PG]
All SQL follows these governing principles:
- [POLYMORPHIC] — one function/query per concern, generic over specific via parameter dispatch and dynamic SQL
- [SET_ALGEBRAIC] — express operations as set transformations; zero row-at-a-time iteration
- [STRONGLY_TYPED] — domain types, composite types, range types; zero untyped `text` columns for structured data
- [PROGRAMMATIC] — variable-driven predicates, parameterized DDL, zero stringly-typed identifiers
- [DECLARATIVE_FIRST] — constraints, generated columns, and RLS policies enforce invariants at the schema level; application logic is last resort
- [SOURCE_CURRENT] — every example uses PostgreSQL semantics
## [01]-[ROUTING]
[REFERENCES]: `validation.md` always loads; the rest load when the task matches.
- [01]-[VALIDATION](references/validation.md): compliance checklist, Effect-SQL alignment, migration safety
- [02]-[DDL](references/ddl.md): schema design, domain/composite/range types, temporal constraints, generated columns, partitioning, lock levels
- [03]-[QUERIES](references/queries.md): CTE algebra, MERGE, window functions, JSON_TABLE, recursive patterns
- [04]-[INDEXES](references/indexes.md): index type selection, partial indexes, covering indexes, maintenance
- [05]-[FUNCTIONS](references/functions.md): polymorphic functions, custom aggregates, procedures, PL/pgSQL dispatch
- [06]-[EXTENSIONS](references/extensions.md): pgvector, pg_trgm, PostGIS, TimescaleDB, pg_cron, pg_partman, pg_duckdb, embeddings, spatial, OLAP
- [07]-[SECURITY](references/security.md): RLS, row-level security, tenant isolation, privileges, audit, pgaudit
- [08]-[OBSERVABILITY](references/observability.md): monitoring, statistics, auto_explain, wait events, lock contention
- [09]-[PERFORMANCE](references/performance.md): tuning, io_uring, JIT, parallel query, vacuum, SSD, NVMe, EXPLAIN
- [10]-[REPLICATION](references/replication.md): replication, publications, subscriptions, conflict tracking, CDC
[SCRIPTS]: run after writing or modifying SQL.
- [01]-[PG_LINT](scripts/pg_lint.sh): doctrine lint over SQL paths; errors block merge, warnings need justification; flags route to `--help`
## [02]-[PARADIGM]
- [IMMUTABILITY]: append-only events, `tstzrange` + `WITHOUT OVERLAPS` versioning, soft-delete via `archived_at` — zero in-place mutation
- [TYPE_ANCHORING]: one `CREATE TYPE` or `CREATE DOMAIN` per semantic concept — columns reference the domain, never redeclaring `CHECK` per table
- [EXPRESSION_CONTROL_FLOW]: `COALESCE`, `NULLIF`, `GREATEST`/`LEAST`, `LATERAL`, `FILTER (WHERE ...)` — `CASE` only for multi-branch projection
- [SET_COMPOSITION]: CTEs as named relational algebra steps; `UNION ALL` over procedural accumulation; `MERGE` over conditional INSERT/UPDATE
- [CONSTRAINT_DRIVEN_INTEGRITY]: DDL validates — `CHECK`, `EXCLUDE`, `WITHOUT OVERLAPS`, `GENERATED ALWAYS AS`; application checks never enforce
- [EXTENSION_FIRST]: pgvector, pg_trgm, PostGIS, TimescaleDB — never hand-roll what an extension owns
## [03]-[CONVENTIONS]
| [INDEX] | [LAYER] | [MECHANISM] | [OWNS] |
| :-----: | :------------- | :-------------------------------- | :------------------------------------------------------------- |
| [01] | Identity | `uuidv7()` | PK generation — timestamp-ordered, B-tree friendly |
| [02] | Temporal | `WITHOUT OVERLAPS` + `PERIOD` | Range integrity — temporal PKs, FKs, exclusion constraints |
| [03] | Projection | Virtual generated columns | Computed fields — zero storage, instant `ALTER TABLE` |
| [04] | Write strategy | `MERGE ... RETURNING OLD/NEW` | Upsert + audit trail in single statement |
| [05] | Type safety | Domain types + composite types | Semantic column typing — branded scalars, structured records |
| [06] | Search | GIN + pg_trgm / pgvector | Full-text, trigram similarity, vector nearest-neighbor |
| [07] | Partitioning | Declarative + pg_partman | Time/hash/list partitioning with automatic lifecycle |
| [08] | Scheduling | pg_cron | In-database job scheduling — maintenance, materialized views |
| [09] | Security | RLS + SECURITY INVOKER | Row-level tenant isolation, least-privilege function execution |
| [10] | Observability | pg_stat_statements + auto_explain | Query fingerprinting, automatic slow-query plan capture |
- Effect-SQL (`@effect/sql` + `@effect/sql-pg`) is the assumed TypeScript integration layer.
- `Model.Class` field modifiers (`Generated`, `FieldOnly`, `FieldExcept`, `Sensitive`) must align with DDL constraints.
- `Generated` fields map to `DEFAULT` or `GENERATED ALWAYS AS` columns.
- All SQL identifiers use `snake_case`; TypeScript receives `camelCase` via `transformResultNames`.
## [04]-[CONTRACTS]
[TYPE_DISCIPLINE]:
- One domain type per semantic concept; column declarations reference the domain, never inline `CHECK` constraints.
- Composite types for structured return values from functions — never `OUT` parameter proliferation.
- Range types (`tstzrange`, `int4range`, custom) for interval semantics — never dual `start`/`end` columns.
- `NOT NULL` is default posture; nullable columns require documented justification.
[QUERY_ALGEBRA]:
- CTEs for named intermediate results; recursive CTEs with `SEARCH BREADTH FIRST` or `CYCLE` for graph traversal.
- `MERGE` with `RETURNING OLD.*, NEW.*, merge_action()` for write-audit fusion.
- Window functions with `GROUPS`/`EXCLUDE` framing where row-count framing is insufficient.
- `JSON_TABLE` / `jsonb_path_query` for structured JSON extraction — never application-side JSON parsing of database-resident JSON.
- `LATERAL JOIN` for correlated subquery materialization — never scalar subqueries in SELECT list.
[INDEX_STRATEGY]:
- Every `WHERE` clause pattern has a corresponding index; partial indexes for selective predicates.
- `INCLUDE` columns for index-only scans on high-frequency read paths.
- GIN for JSONB containment (`@>`), array overlap (`&&`), full-text (`@@`).
- GiST for range overlap, spatial queries, nearest-neighbor when combined with `ORDER BY <-> LIMIT`.
- BRIN for append-only monotonic columns (timestamps, serial IDs) — orders of magnitude smaller than B-tree.
[SECURITY]:
- RLS enabled on every tenant-scoped table; policies use fail-closed `nullif(current_setting('app.current_tenant', true), '')` tenant scoping.
- Functions default to `SECURITY INVOKER` (always the default); `SECURITY DEFINER` only with `SET search_path = pg_catalog, public`.
- Column-level `GRANT` for sensitive fields — never rely on view-based column hiding alone.
[PERFORMANCE]:
- `EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS)` is the verification tool; assertions against plan shape, not just row counts.
- AIO (`io_method = io_uring`) for sequential scan and vacuum workloads on Linux.
- Parallel query enabled for aggregation, hash join, index scan — `max_parallel_workers_per_gather` tuned to workload.
- `FOR UPDATE SKIP LOCKED` for concurrent batch processing — never `SELECT ... FOR UPDATE` without `SKIP LOCKED` on queue tables.
## [05]-[ANTI_PATTERNS]
| [INDEX] | [LABEL] | [SYMPTOM] |
| :-----: | :---------------------------- | :----------------------------------------------------------------------------- |
| [01] | STRING_TYPING | `text` for structured data (JSON, enum values, composite structures) |
| [02] | DUAL_COLUMN_RANGE | `start_date`/`end_date` instead of `tstzrange` with exclusion constraint |
| [03] | IMPERATIVE_BATCH | PL/pgSQL `LOOP` with row-at-a-time `UPDATE` instead of set-based `MERGE`/CTE |
| [04] | INDEX_SPRAWL | Redundant single-column indexes subsumed by existing composite indexes |
| [05] | NULLABLE_DEFAULT | Columns nullable without documented justification |
| [06] | TRIGGER_LOGIC | Business logic in triggers instead of `MERGE RETURNING` or generated columns |
| [07] | OFFSET_PAGINATION | `LIMIT/OFFSET` instead of keyset pagination for client-facing endpoints |
| [08] | SECURITY_DEFINER_LEAK | `SECURITY DEFINER` without `SET search_path` — search_path injection vector |
| [09] | STRINGLY_POLICY | RLS policy with hardcoded literals instead of `current_setting()` |
| [10] | FUNCTION_PROLIFERATION | Separate functions for each query variant instead of one polymorphic function |
| [11] | APPLICATION_SIDE_JSON | Fetching raw JSONB and parsing in application instead of `jsonb_path_query` |
| [12] | MANUAL_PARTITION | Hand-written partition creation instead of pg_partman lifecycle management |
| [13] | UNVALIDATED_CONSTRAINT | `ADD CONSTRAINT ... NOT VALID` without subsequent `VALIDATE CONSTRAINT` |
| [14] | IF_THEN_DISPATCH | PL/pgSQL `IF p_op = 'get' THEN ... ELSIF` instead of VALUES-based dynamic SQL |
| [15] | NONCOMPOSABLE_CAGG | `PERCENTILE_CONT` in hierarchical CAGG; non-composable across tiers |
| [16] | LEGACY_UUID | Non-ordered UUID generation on new ordered PKs where `uuidv7()` fits better |
| [17] | STALE_HEALTH_VIEW | Materialized views for real-time health monitoring instead of inline queries |
| [18] | EXCLUDE_OVER_WITHOUT_OVERLAPS | EXCLUDE instead of WITHOUT OVERLAPS PK/UNIQUE for temporal overlap |
| [19] | RAW_UUID_ID | Raw `S.UUID` for PK/FK instead of `S.UUID.pipe(S.brand('EntityId'))` |
| [20] | BARE_FOR_UPDATE | `FOR UPDATE` without `SKIP LOCKED` on batch/queue processing patterns |
| [21] | NULL_UNSAFE_ANTIJOIN | `NOT IN (SELECT ...)` instead of `NOT EXISTS`; NULL in subquery yields UNKNOWN |
| [22] | DISTINCT_OVER_EXISTS | `SELECT DISTINCT` on joined data; use `EXISTS` semi-join (avoids sort/dedup) |
## [06]-[FIRST_CLASS_EXTENSIONS]
| [INDEX] | [EXTENSION] | [OWNS] | [LOAD_WHEN] |
| :-----: | :------------------- | :------------------------------------------------------ | :-------------------------------------- |
| [01] | `pgvector` | Vector storage, HNSW/IVFFlat/DiskANN indexes | Embedding search, similarity queries |
| [02] | `pgvectorscale` | DiskANN index, Statistical Binary Quantization | >1M vectors, memory-constrained |
| [03] | `pg_search` | BM25 full-text via Tantivy, `@@@` operator | Search-quality ranking, hybrid search |
| [04] | `pg_trgm` | Trigram similarity, GIN trigram indexes, `%` operator | Fuzzy text search, typo tolerance |
| [05] | `PostGIS` | Geometry/geography types, spatial indexes, ST\_\* funcs | Geospatial queries, proximity search |
| [06] | `TimescaleDB` | Hypertables, continuous aggregates, compression | Time-series ingestion, rollup queries |
| [07] | `pg_cron` | In-database scheduled jobs | Materialized view refresh, maintenance |
| [08] | `pg_partman` | Partition lifecycle management | Non-time-series partitioning |
| [09] | `pg_duckdb` | Embedded DuckDB, analytical acceleration, lake access | OLAP queries, Parquet/Iceberg reads |
| [10] | `pg_jsonschema` | JSONB validation via JSON Schema CHECK constraints | Structured JSONB columns |
| [11] | `btree_gist` | GiST equality operators for EXCLUDE constraints | Range + equality exclusion constraints |
| [12] | `bloom` | Bloom filter index for wide-table equality | >5 columns, arbitrary WHERE combos |
| [13] | `pg_stat_statements` | Query fingerprinting, execution statistics | Performance analysis, regression detect |
| [14] | `pgaudit` | Compliance-grade audit logging (session + object) | SOC 2, HIPAA, PCI-DSS compliance |
## [07]-[VALIDATION_GATE]
After writing or modifying SQL, run in order:
1. [AUTOMATED_LINT]: `bash ${CLAUDE_SKILL_DIR}/scripts/pg_lint.sh [PATH...]`; errors block merge, warnings need justification; flags route to `--help`.
2. [MANUAL_CHECKLIST]: `references/validation.md` — compliance gates not automatable (Effect-SQL alignment, migration safety, lock-level awareness).
Files in this skill
- SKILL.md
- references/ddl.md
- references/extensions.md
- references/functions.md
- references/indexes.md
- references/observability.md
- references/performance.md
- references/queries.md
- references/replication.md
- references/security.md
- references/validation.md
- scripts/pg_lint.sh
Attribution
Comments
Loading comments…