{"id":"b4343c6a-7c42-488c-9b46-5b81d6ebf222","shortId":"9YTc2c","kind":"skill","title":"postgresql","tagline":"Design a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and advanced features","description":"# PostgreSQL Table Design \n\n## Use this skill when\n\n- Designing a schema for PostgreSQL\n- Selecting data types and constraints\n- Planning indexes, partitions, or RLS policies\n- Reviewing tables for scale and maintainability\n\n## Do not use this skill when\n\n- You are targeting a non-PostgreSQL database\n- You only need query tuning without schema changes\n- You require a DB-agnostic modeling guide\n\n## Instructions\n\n1. Capture entities, access patterns, and scale targets (rows, QPS, retention).\n2. Choose data types and constraints that enforce invariants.\n3. Add indexes for real query paths and validate with `EXPLAIN`.\n4. Plan partitioning or RLS where required by scale or access control.\n5. Review migration impact and apply changes safely.\n\n## Safety\n\n- Avoid destructive DDL on production without backups and a rollback plan.\n- Use migrations and staging validation before applying schema changes.\n\n## Core Rules\n\n- Define a **PRIMARY KEY** for reference tables (users, orders, etc.). Not always needed for time-series/event/log data. When used, prefer `BIGINT GENERATED ALWAYS AS IDENTITY`; use `UUID` only when global uniqueness/opacity is needed.\n- **Normalize first (to 3NF)** to eliminate data redundancy and update anomalies; denormalize **only** for measured, high-ROI reads where join performance is proven problematic. Premature denormalization creates maintenance burden.\n- Add **NOT NULL** everywhere it’s semantically required; use **DEFAULT**s for common values.\n- Create **indexes for access paths you actually query**: PK/unique (auto), **FK columns (manual!)**, frequent filters/sorts, and join keys.\n- Prefer **TIMESTAMPTZ** for event time; **NUMERIC** for money; **TEXT** for strings; **BIGINT** for integer values, **DOUBLE PRECISION** for floats (or `NUMERIC` for exact decimal arithmetic).\n\n## PostgreSQL “Gotchas”\n\n- **Identifiers**: unquoted → lowercased. Avoid quoted/mixed-case names. Convention: use `snake_case` for table/column names.\n- **Unique + NULLs**: UNIQUE allows multiple NULLs. Use `UNIQUE (...) NULLS NOT DISTINCT` (PG15+) to restrict to one NULL.\n- **FK indexes**: PostgreSQL **does not** auto-index FK columns. Add them.\n- **No silent coercions**: length/precision overflows error out (no truncation). Example: inserting 999 into `NUMERIC(2,0)` fails with error, unlike some databases that silently truncate or round.\n- **Sequences/identity have gaps** (normal; don't \"fix\"). Rollbacks, crashes, and concurrent transactions create gaps in ID sequences (1, 2, 5, 6...). This is expected behavior—don't try to make IDs consecutive.\n- **Heap storage**: no clustered PK by default (unlike SQL Server/MySQL InnoDB); `CLUSTER` is one-off reorganization, not maintained on subsequent inserts. Row order on disk is insertion order unless explicitly clustered.\n- **MVCC**: updates/deletes leave dead tuples; vacuum handles them—design to avoid hot wide-row churn.\n\n## Data Types\n\n- **IDs**: `BIGINT GENERATED ALWAYS AS IDENTITY` preferred (`GENERATED BY DEFAULT` also fine); `UUID` when merging/federating/used in a distributed system or for opaque IDs. Generate with `uuidv7()` (preferred if using PG18+) or `gen_random_uuid()` (if using an older PG version).\n- **Integers**: prefer `BIGINT` unless storage space is critical; `INTEGER` for smaller ranges; avoid `SMALLINT` unless constrained.\n- **Floats**: prefer `DOUBLE PRECISION` over `REAL` unless storage space is critical. Use `NUMERIC` for exact decimal arithmetic.\n- **Strings**: prefer `TEXT`; if length limits needed, use `CHECK (LENGTH(col) <= n)` instead of `VARCHAR(n)`; avoid `CHAR(n)`. Use `BYTEA` for binary data. Large strings/binary (>2KB default threshold) automatically stored in TOAST with compression. TOAST storage: `PLAIN` (no TOAST), `EXTENDED` (compress + out-of-line), `EXTERNAL` (out-of-line, no compress), `MAIN` (compress, keep in-line if possible). Default `EXTENDED` usually optimal. Control with `ALTER TABLE tbl ALTER COLUMN col SET STORAGE strategy` and `ALTER TABLE tbl SET (toast_tuple_target = 4096)` for threshold. Case-insensitive: for locale/accent handling use non-deterministic collations; for plain ASCII use expression indexes on `LOWER(col)` (preferred unless column needs case-insensitive PK/FK/UNIQUE) or `CITEXT`.\n- **Money**: `NUMERIC(p,s)` (never float).\n- **Time**: `TIMESTAMPTZ` for timestamps; `DATE` for date-only; `INTERVAL` for durations. Avoid `TIMESTAMP` (without timezone). Use `now()` for transaction start time, `clock_timestamp()` for current wall-clock time.\n- **Booleans**: `BOOLEAN` with `NOT NULL` constraint unless tri-state values are required.\n- **Enums**: `CREATE TYPE ... AS ENUM` for small, stable sets (e.g. US states, days of week). For business-logic-driven and evolving values (e.g. order statuses) → use TEXT (or INT) + CHECK or lookup table.\n- **Arrays**: `TEXT[]`, `INTEGER[]`, etc. Use for ordered lists where you query elements. Index with **GIN** for containment (`@>`, `<@`) and overlap (`&&`) queries. Access: `arr[1]` (1-indexed), `arr[1:3]` (slicing). Good for tags, categories; avoid for relations—use junction tables instead. Literal syntax: `'{val1,val2}'` or `ARRAY[val1,val2]`.\n- **Range types**: `daterange`, `numrange`, `tstzrange` for intervals. Support overlap (`&&`), containment (`@>`), operators. Index with **GiST**. Good for scheduling, versioning, numeric ranges. Pick a bounds scheme and use it consistently; prefer `[)` (inclusive/exclusive) by default.\n- **Network types**: `INET` for IP addresses, `CIDR` for network ranges, `MACADDR` for MAC addresses. Support network operators (`<<`, `>>`, `&&`).\n- **Geometric types**: `POINT`, `LINE`, `POLYGON`, `CIRCLE` for 2D spatial data. Index with **GiST**. Consider **PostGIS** for advanced spatial features.\n- **Text search**: `TSVECTOR` for full-text search documents, `TSQUERY` for search queries. Index `tsvector` with **GIN**. Always specify language: `to_tsvector('english', col)` and `to_tsquery('english', 'query')`. Never use single-argument versions. This applies to both index expressions and queries.\n- **Domain types**: `CREATE DOMAIN email AS TEXT CHECK (VALUE ~ '^[^@]+@[^@]+$')` for reusable custom types with validation. Enforces constraints across tables.\n- **Composite types**: `CREATE TYPE address AS (street TEXT, city TEXT, zip TEXT)` for structured data within columns. Access with `(col).field` syntax.\n- **JSONB**: preferred over JSON; index with **GIN**. Use only for optional/semi-structured attrs. ONLY use JSON if the original ordering of the contents MUST be preserved.\n- **Vector types**: `vector` type by `pgvector` for vector similarity search for embeddings.\n\n\n### Do not use the following data types\n- DO NOT use `timestamp` (without time zone); DO use `timestamptz` instead.\n- DO NOT use `char(n)` or `varchar(n)`; DO use `text` instead.\n- DO NOT use `money` type; DO use `numeric` instead.\n- DO NOT use `timetz` type; DO use `timestamptz` instead.\n- DO NOT use `timestamptz(0)` or any other precision specification; DO use `timestamptz` instead\n- DO NOT use `serial` type; DO use `generated always as identity` instead.\n\n\n## Table Types\n\n- **Regular**: default; fully durable, logged.\n- **TEMPORARY**: session-scoped, auto-dropped, not logged. Faster for scratch work.\n- **UNLOGGED**: persistent but not crash-safe. Faster writes; good for caches/staging.\n\n## Row-Level Security\n\nEnable with `ALTER TABLE tbl ENABLE ROW LEVEL SECURITY`. Create policies: `CREATE POLICY user_access ON orders FOR SELECT TO app_users USING (user_id = current_user_id())`. Built-in user-based access control at the row level.\n\n## Constraints\n\n- **PK**: implicit UNIQUE + NOT NULL; creates a B-tree index.\n- **FK**: specify `ON DELETE/UPDATE` action (`CASCADE`, `RESTRICT`, `SET NULL`, `SET DEFAULT`). Add explicit index on referencing column—speeds up joins and prevents locking issues on parent deletes/updates. Use `DEFERRABLE INITIALLY DEFERRED` for circular FK dependencies checked at transaction end.\n- **UNIQUE**: creates a B-tree index; allows multiple NULLs unless `NULLS NOT DISTINCT` (PG15+). Standard behavior: `(1, NULL)` and `(1, NULL)` are allowed. With `NULLS NOT DISTINCT`: only one `(1, NULL)` allowed. Prefer `NULLS NOT DISTINCT` unless you specifically need duplicate NULLs.\n- **CHECK**: row-local constraints; NULL values pass the check (three-valued logic). Example: `CHECK (price > 0)` allows NULL prices. Combine with `NOT NULL` to enforce: `price NUMERIC NOT NULL CHECK (price > 0)`.\n- **EXCLUDE**: prevents overlapping values using operators. `EXCLUDE USING gist (room_id WITH =, booking_period WITH &&)` prevents double-booking rooms. Requires appropriate index type (often GiST).\n\n## Indexing\n\n- **B-tree**: default for equality/range queries (`=`, `<`, `>`, `BETWEEN`, `ORDER BY`)\n- **Composite**: order matters—index used if equality on leftmost prefix (`WHERE a = ? AND b > ?` uses index on `(a,b)`, but `WHERE b = ?` does not). Put most selective/frequently filtered columns first.\n- **Covering**: `CREATE INDEX ON tbl (id) INCLUDE (name, email)` - includes non-key columns for index-only scans without visiting table.\n- **Partial**: for hot subsets (`WHERE status = 'active'` → `CREATE INDEX ON tbl (user_id) WHERE status = 'active'`). Any query with `status = 'active'` can use this index.\n- **Expression**: for computed search keys (`CREATE INDEX ON tbl (LOWER(email))`). Expression must match exactly in WHERE clause: `WHERE LOWER(email) = 'user@example.com'`.\n- **GIN**: JSONB containment/existence, arrays (`@>`, `?`), full-text search (`@@`)\n- **GiST**: ranges, geometry, exclusion constraints\n- **BRIN**: very large, naturally ordered data (time-series)—minimal storage overhead. Effective when row order on disk correlates with indexed column (insertion order or after `CLUSTER`).\n\n## Partitioning\n\n- Use for very large tables (>100M rows) where queries consistently filter on partition key (often time/date).\n- Alternate use: use for tables where data maintenance tasks dictates e.g. data pruned or bulk replaced periodically\n- **RANGE**: common for time-series (`PARTITION BY RANGE (created_at)`). Create partitions: `CREATE TABLE logs_2024_01 PARTITION OF logs FOR VALUES FROM ('2024-01-01') TO ('2024-02-01')`. **TimescaleDB** automates time-based or ID-based partitioning with retention policies and compression.\n- **LIST**: for discrete values (`PARTITION BY LIST (region)`). Example: `FOR VALUES IN ('us-east', 'us-west')`.\n- **HASH**: for even distribution when no natural key (`PARTITION BY HASH (user_id)`). Creates N partitions with modulus.\n- **Constraint exclusion**: requires `CHECK` constraints on partitions for query planner to prune. Auto-created for declarative partitioning (PG10+).\n- Prefer declarative partitioning or hypertables. Do NOT use table inheritance.\n- **Limitations**: no global UNIQUE constraints—include partition key in PK/UNIQUE. FKs from partitioned tables not supported; use triggers.\n\n## Special Considerations\n\n### Update-Heavy Tables\n\n- **Separate hot/cold columns**—put frequently updated columns in separate table to minimize bloat.\n- **Use `fillfactor=90`** to leave space for HOT updates that avoid index maintenance.\n- **Avoid updating indexed columns**—prevents beneficial HOT updates.\n- **Partition by update patterns**—separate frequently updated rows in a different partition from stable data.\n\n### Insert-Heavy Workloads\n\n- **Minimize indexes**—only create what you query; every index slows inserts.\n- **Use `COPY` or multi-row `INSERT`** instead of single-row inserts.\n- **UNLOGGED tables** for rebuildable staging data—much faster writes.\n- **Defer index creation** for bulk loads—>drop index, load data, recreate indexes.\n- **Partition by time/hash** to distribute load. **TimescaleDB** automates partitioning and compression of insert-heavy data.\n- **Use a natural key for primary key** such as a (timestamp, device_id) if enforcing global uniqueness is important many insert-heavy tables don't need a primary key at all.\n- If you do need a surrogate key, **Prefer `BIGINT GENERATED ALWAYS AS IDENTITY` over `UUID`**.\n\n### Upsert-Friendly Design\n\n- **Requires UNIQUE index** on conflict target columns—`ON CONFLICT (col1, col2)` needs exact matching unique index (partial indexes don't work).\n- **Use `EXCLUDED.column`** to reference would-be-inserted values; only update columns that actually changed to reduce write overhead.\n- **`DO NOTHING` faster** than `DO UPDATE` when no actual update needed.\n\n### Safe Schema Evolution\n\n- **Transactional DDL**: most DDL operations can run in transactions and be rolled back—`BEGIN; ALTER TABLE...; ROLLBACK;` for safe testing.\n- **Concurrent index creation**: `CREATE INDEX CONCURRENTLY` avoids blocking writes but can't run in transactions.\n- **Volatile defaults cause rewrites**: adding `NOT NULL` columns with volatile defaults (e.g., `now()`, `gen_random_uuid()`) rewrites entire table. Non-volatile defaults are fast.\n- **Drop constraints before columns**: `ALTER TABLE DROP CONSTRAINT` then `DROP COLUMN` to avoid dependency issues.\n- **Function signature changes**: `CREATE OR REPLACE` with different arguments creates overloads, not replacements. DROP old version if no overload desired.\n\n## Generated Columns\n\n- `... GENERATED ALWAYS AS (<expr>) STORED` for computed, indexable fields. PG18+ adds `VIRTUAL` columns (computed on read, not stored).\n\n## Extensions\n\n- **`pgcrypto`**: `crypt()` for password hashing.\n- **`uuid-ossp`**: alternative UUID functions; prefer `pgcrypto` for new projects.\n- **`pg_trgm`**: fuzzy text search with `%` operator, `similarity()` function. Index with GIN for `LIKE '%pattern%'` acceleration.\n- **`citext`**: case-insensitive text type. Prefer expression indexes on `LOWER(col)` unless you need case-insensitive constraints.\n- **`btree_gin`/`btree_gist`**: enable mixed-type indexes (e.g., GIN index on both JSONB and text columns).\n- **`hstore`**: key-value pairs; mostly superseded by JSONB but useful for simple string mappings.\n- **`timescaledb`**: essential for time-series—automated partitioning, retention, compression, continuous aggregates.\n- **`postgis`**: comprehensive geospatial support beyond basic geometric types—essential for location-based applications.\n- **`pgvector`**: vector similarity search for embeddings.\n- **`pgaudit`**: audit logging for all database activity.\n\n## JSONB Guidance\n\n- Prefer `JSONB` with **GIN** index.\n- Default: `CREATE INDEX ON tbl USING GIN (jsonb_col);` → accelerates:\n  - **Containment** `jsonb_col @> '{\"k\":\"v\"}'`\n  - **Key existence** `jsonb_col ? 'k'`, **any/all keys** `?\\|`, `?&`\n  - **Path containment** on nested docs\n  - **Disjunction** `jsonb_col @> ANY(ARRAY['{\"status\":\"active\"}', '{\"status\":\"pending\"}'])`\n- Heavy `@>` workloads: consider opclass `jsonb_path_ops` for smaller/faster containment-only indexes:\n  - `CREATE INDEX ON tbl USING GIN (jsonb_col jsonb_path_ops);`\n  - **Trade-off**: loses support for key existence (`?`, `?|`, `?&`) queries—only supports containment (`@>`)\n- Equality/range on a specific scalar field: extract and index with B-tree (generated column or expression):\n  - `ALTER TABLE tbl ADD COLUMN price INT GENERATED ALWAYS AS ((jsonb_col->>'price')::INT) STORED;`\n  - `CREATE INDEX ON tbl (price);`\n  - Prefer queries like `WHERE price BETWEEN 100 AND 500` (uses B-tree) over `WHERE (jsonb_col->>'price')::INT BETWEEN 100 AND 500` without index.\n- Arrays inside JSONB: use GIN + `@>` for containment (e.g., tags). Consider `jsonb_path_ops` if only doing containment.\n- Keep core relations in tables; use JSONB for optional/variable attributes.\n- Use constraints to limit allowed JSONB values in a column e.g. `config JSONB NOT NULL CHECK(jsonb_typeof(config) = 'object')`\n\n\n## Examples\n\n### Users\n\n```sql\nCREATE TABLE users (\n  user_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,\n  email TEXT NOT NULL UNIQUE,\n  name TEXT NOT NULL,\n  created_at TIMESTAMPTZ NOT NULL DEFAULT now()\n);\nCREATE UNIQUE INDEX ON users (LOWER(email));\nCREATE INDEX ON users (created_at);\n```\n\n### Orders\n\n```sql\nCREATE TABLE orders (\n  order_id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,\n  user_id BIGINT NOT NULL REFERENCES users(user_id),\n  status TEXT NOT NULL DEFAULT 'PENDING' CHECK (status IN ('PENDING','PAID','CANCELED')),\n  total NUMERIC(10,2) NOT NULL CHECK (total > 0),\n  created_at TIMESTAMPTZ NOT NULL DEFAULT now()\n);\nCREATE INDEX ON orders (user_id);\nCREATE INDEX ON orders (created_at);\n```\n\n### JSONB\n\n```sql\nCREATE TABLE profiles (\n  user_id BIGINT PRIMARY KEY REFERENCES users(user_id),\n  attrs JSONB NOT NULL DEFAULT '{}',\n  theme TEXT GENERATED ALWAYS AS (attrs->>'theme') STORED\n);\nCREATE INDEX profiles_attrs_gin ON profiles USING GIN (attrs);\n```","tags":["postgresql","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity-skills"],"capabilities":["skill","source-sickn33","skill-postgresql","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/postgresql","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34616 github stars · SKILL.md body (16,685 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-23T00:51:24.508Z","embedding":null,"createdAt":"2026-04-18T21:42:34.861Z","updatedAt":"2026-04-23T00:51:24.508Z","lastSeenAt":"2026-04-23T00:51:24.508Z","tsv":"'-01':1453,1454,1458 '-02':1457 '/event/log':172 '0':336,992,1201,1217,2295 '01':1445 '1':81,365,725,726,729,1158,1161,1171 '10':2289 '100':2142,2156 '100m':1400 '2':92,335,366,2290 '2024':1444,1452,1456 '2d':807 '2kb':529 '3':101,730 '3nf':193 '4':112 '4096':587 '5':124,367 '500':2144,2158 '6':368 '90':1578 '999':332 'acceler':1928,2036 'access':84,122,237,723,898,1064,1084 'across':879 'action':1106 'activ':1313,1322,1327,2019,2060 'actual':240,1762,1776 'ad':1821 'add':102,220,319,1113,1888,2119 'address':788,796,885 'advanc':19,816 'aggreg':1992 'agnost':77 'allow':295,1148,1164,1173,1202,2192 'also':440 'alter':570,573,580,1052,1796,1846,2116 'altern':1411,1905 'alway':166,179,433,836,1010,1719,1880,2124,2218,2261,2337 'anomali':200 'any/all':2047 'app':1070 'appli':129,150,855 'applic':2006 'appropri':1239 'argument':852,1865 'arithmet':276,502 'arr':724,728 'array':703,748,1357,2058,2161 'ascii':603 'attr':914,2329,2339,2345,2351 'attribut':2187 'audit':2014 'auto':243,315,1026,1523 'auto-cr':1522 'auto-drop':1025 'auto-index':314 'autom':1460,1668,1987 'automat':532 'avoid':133,282,422,482,519,638,736,1586,1589,1808,1854 'b':1099,1145,1246,1268,1273,1276,2110,2147 'b-tree':1098,1144,1245,2109,2146 'back':1794 'backup':139 'base':1083,1463,1467,2005 'basic':1998 'begin':1795 'behavior':372,1157 'benefici':1594 'best':10 'best-practic':9 'beyond':1997 'bigint':177,263,431,472,1717,2216,2259,2268,2322 'binari':525 'bloat':1575 'block':1809 'book':1230,1236 'boolean':656,657 'bound':773 'brin':1367 'btree':1948,1950 'built':1079 'built-in':1078 'bulk':1425,1653 'burden':219 'busi':686 'business-logic-driven':685 'bytea':523 'caches/staging':1045 'cancel':2286 'captur':82 'cascad':1107 'case':288,591,615,1931,1945 'case-insensit':590,614,1930,1944 'categori':735 'caus':1819 'chang':71,130,152,1763,1859 'char':520,961 'check':511,699,869,1137,1184,1193,1199,1215,1513,2203,2281,2293 'choos':93 'churn':427 'cidr':789 'circl':805 'circular':1134 'citext':619,1929 'citi':889 'claus':1349 'clock':648,654 'cluster':383,391,411,1393 'coercion':323 'col':513,575,609,842,900,1940,2035,2039,2045,2056,2083,2127,2152 'col1':1737 'col2':1738 'collat':600 'column':245,318,574,612,897,1118,1283,1298,1388,1565,1569,1592,1734,1760,1824,1845,1852,1878,1890,1965,2113,2120,2197 'combin':1205 'common':232,1429 'composit':881,1255 'comprehens':1994 'compress':537,544,555,557,1473,1671,1990 'comput':1334,1884,1891 'concurr':358,1802,1807 'config':2199,2206 'conflict':1732,1736 'consecut':379 'consid':813,2065,2170 'consider':1558 'consist':778,1404 'constrain':485 'constraint':15,37,97,661,878,1090,1188,1366,1510,1514,1543,1843,1849,1947,2189 'contain':719,760,2037,2050,2073,2098,2167,2177 'containment-on':2072 'containment/existence':1356 'content':924 'continu':1991 'control':123,568,1085 'convent':285 'copi':1628 'core':153,2179 'correl':1385 'cover':8,1285 'crash':356,1039 'crash-saf':1038 'creat':217,234,360,670,864,883,1059,1061,1096,1142,1286,1314,1337,1437,1439,1441,1505,1524,1619,1805,1860,1866,2028,2076,2131,2211,2232,2239,2246,2250,2254,2296,2303,2309,2313,2317,2342 'creation':1651,1804 'critic':477,496 'crypt':1898 'current':651,1075 'custom':873 'data':12,34,94,173,196,428,526,809,895,945,1372,1417,1422,1611,1645,1658,1676 'databas':63,342,2018 'date':630,633 'date-on':632 'daterang':753 'day':681 'db':76 'db-agnost':75 'ddl':135,1783,1785 'dead':415 'decim':275,501 'declar':1526,1530 'default':229,386,439,530,564,782,1017,1112,1248,1818,1827,1839,2027,2237,2279,2301,2333 'defer':1132,1649 'deferr':1130 'defin':155 'delete/update':1105 'deletes/updates':1128 'denorm':201,216 'depend':1136,1855 'design':2,23,28,420,1727 'desir':1876 'destruct':134 'determinist':599 'devic':1688 'dictat':1420 'differ':1607,1864 'discret':1476 'disjunct':2054 'disk':405,1384 'distinct':302,1154,1168,1177 'distribut':447,1495,1665 'doc':2053 'document':827 'domain':862,865 'doubl':267,488,1235 'double-book':1234 'driven':688 'drop':1027,1655,1842,1848,1851,1870 'duplic':1182 'durabl':1019 'durat':637 'e.g':678,692,1421,1828,1957,2168,2198 'east':1488 'effect':1379 'element':714 'elimin':195 'email':866,1293,1342,1352,2223,2245 'embed':939,2012 'enabl':1050,1055,1952 'end':1140 'enforc':99,877,1210,1691 'english':841,846 'entir':1834 'entiti':83 'enum':669,673 'equal':1261 'equality/range':1250,2099 'error':326,339 'essenti':1982,2001 'etc':164,706 'even':1494 'event':255 'everi':1623 'everywher':223 'evolut':1781 'evolv':690 'exact':274,500,1346,1740 'exampl':330,1198,1482,2208 'exclud':1218,1224 'excluded.column':1750 'exclus':1365,1511 'exist':2043,2094 'expect':371 'explain':111 'explicit':410,1114 'express':605,859,1332,1343,1936,2115 'extend':543,565 'extens':1896 'extern':549 'extract':2105 'fail':337 'fast':1841 'faster':1030,1041,1647,1770 'featur':20,818 'field':901,1886,2104 'fillfactor':1577 'filter':1282,1405 'filters/sorts':248 'fine':441 'first':191,1284 'fix':354 'fk':244,309,317,1102,1135 'fks':1549 'float':270,486,625 'follow':944 'frequent':247,1567,1602 'friend':1726 'full':824,1359 'full-text':823,1358 'fulli':1018 'function':1857,1907,1921 'fuzzi':1915 'gap':350,361 'gen':461,1830 'generat':178,432,437,453,1009,1718,1877,1879,2112,2123,2217,2260,2336 'geometr':800,1999 'geometri':1364 'geospati':1995 'gin':717,835,909,1354,1924,1949,1958,2025,2033,2081,2165,2346,2350 'gist':764,812,1226,1243,1362,1951 'global':186,1541,1692 'good':732,765,1043 'gotcha':278 'guid':79 'guidanc':2021 'handl':418,595 'hash':1492,1502,1901 'heap':380 'heavi':1561,1614,1675,1699,2063 'high':206 'high-roi':205 'hot':423,1309,1583,1595 'hot/cold':1564 'hstore':1966 'hypert':1533 'id':363,378,430,452,1074,1077,1228,1290,1319,1466,1504,1689,2215,2258,2267,2274,2308,2321,2328 'id-bas':1465 'ident':181,435,1012,1721,2220,2263 'identifi':279 'impact':127 'implicit':1092 'import':1695 'in-lin':559 'includ':1291,1294,1544 'inclusive/exclusive':780 'index':14,39,103,235,310,316,606,715,727,762,810,832,858,907,1101,1115,1147,1240,1244,1258,1270,1287,1301,1315,1331,1338,1387,1587,1591,1617,1624,1650,1656,1660,1730,1743,1745,1803,1806,1885,1922,1937,1956,1959,2026,2029,2075,2077,2107,2132,2160,2241,2247,2304,2310,2343 'index-on':1300 'inet':785 'inherit':1538 'initi':1131 'innodb':390 'insensit':592,616,1932,1946 'insert':331,401,407,1389,1613,1626,1633,1639,1674,1698,1756 'insert-heavi':1612,1673,1697 'insid':2162 'instead':515,742,957,969,978,987,1001,1013,1634 'instruct':80 'int':698,2122,2129,2154 'integ':265,470,478,705 'interv':635,757 'invari':100 'ip':787 'issu':1125,1856 'join':210,250,1121 'json':906,917 'jsonb':903,1355,1962,1974,2020,2023,2034,2038,2044,2055,2067,2082,2084,2126,2151,2163,2171,2184,2193,2200,2204,2315,2330 'junction':740 'k':2040,2046 'keep':558,2178 'key':158,251,1297,1336,1408,1499,1546,1680,1683,1706,1715,1968,2042,2048,2093,2222,2265,2324 'key-valu':1967 'languag':838 'larg':527,1369,1398 'leav':414,1580 'leftmost':1263 'length':507,512 'length/precision':324 'level':1048,1057,1089 'like':1926,2138 'limit':508,1539,2191 'line':548,553,561,803 'list':710,1474,1480 'liter':743 'load':1654,1657,1666 'local':1187 'locale/accent':594 'locat':2004 'location-bas':2003 'lock':1124 'log':1020,1029,1443,1448,2015 'logic':687,1197 'lookup':701 'lose':2090 'lower':608,1341,1351,1939,2244 'lowercas':281 'mac':795 'macaddr':793 'main':556 'maintain':49,398 'mainten':218,1418,1588 'make':377 'mani':1696 'manual':246 'map':1980 'match':1345,1741 'matter':1257 'measur':204 'merging/federating/used':444 'migrat':126,145 'minim':1376,1574,1616 'mix':1954 'mixed-typ':1953 'model':78 'modulus':1509 'money':259,620,973 'most':1971 'much':1646 'multi':1631 'multi-row':1630 'multipl':296,1149 'must':925,1344 'mvcc':412 'n':514,518,521,962,965,1506 'name':284,291,1292,2228 'natur':1370,1498,1679 'need':66,167,189,509,613,1181,1703,1712,1739,1778,1943 'nest':2052 'network':783,791,798 'never':624,848 'new':1911 'non':61,598,1296,1837 'non-determinist':597 'non-key':1295 'non-postgresql':60 'non-volatil':1836 'normal':190,351 'noth':1769 'null':222,293,297,300,308,660,1095,1110,1150,1152,1159,1162,1166,1172,1175,1183,1189,1203,1208,1214,1823,2202,2226,2231,2236,2270,2278,2292,2300,2332 'numer':257,272,334,498,621,769,977,1212,2288 'numrang':754 'object':2207 'often':1242,1409 'old':1871 'older':467 'one':307,394,1170 'one-off':393 'op':2069,2086,2173 'opaqu':451 'opclass':2066 'oper':761,799,1223,1786,1919 'optim':567 'optional/semi-structured':913 'optional/variable':2186 'order':163,403,408,693,709,921,1066,1253,1256,1371,1382,1390,2252,2256,2257,2306,2312 'origin':920 'ossp':1904 'out-of-lin':545,550 'overflow':325 'overhead':1378,1767 'overlap':721,759,1220 'overload':1867,1875 'p':622 'paid':2285 'pair':1970 'parent':1127 'partial':1307,1744 'partit':40,114,1394,1407,1434,1440,1446,1468,1478,1500,1507,1516,1527,1531,1545,1551,1597,1608,1661,1669,1988 'pass':1191 'password':1900 'path':107,238,2049,2068,2085,2172 'pattern':17,85,1600,1927 'pend':2062,2280,2284 'perform':16,211 'period':1231,1427 'persist':1035 'pg':468,1913 'pg10':1528 'pg15':303,1155 'pg18':459,1887 'pgaudit':2013 'pgcrypto':1897,1909 'pgvector':933,2007 'pick':771 'pk':384,1091 'pk/fk/unique':617 'pk/unique':242,1548 'plain':540,602 'plan':38,113,143 'planner':1519 'point':802 'polici':43,1060,1062,1471 'polygon':804 'possibl':563 'postgi':814,1993 'postgresql':1,5,21,32,62,277,311 'postgresql-specif':4 'practic':11 'precis':268,489,996 'prefer':176,252,436,456,471,487,504,610,779,904,1174,1529,1716,1908,1935,2022,2136 'prefix':1264 'prematur':215 'preserv':927 'prevent':1123,1219,1233,1593 'price':1200,1204,1211,1216,2121,2128,2135,2140,2153 'primari':157,1682,1705,2221,2264,2323 'problemat':214 'product':137 'profil':2319,2344,2348 'project':1912 'proven':213 'prune':1423,1521 'put':1279,1566 'qps':90 'queri':67,106,241,713,722,831,847,861,1251,1324,1403,1518,1622,2095,2137 'quoted/mixed-case':283 'random':462,1831 'rang':481,751,770,792,1363,1428,1436 'read':208,1893 'real':105,491 'rebuild':1643 'recreat':1659 'reduc':1765 'redund':197 'refer':160,1752,2271,2325 'referenc':1117 'region':1481 'regular':1016 'relat':738,2180 'reorgan':396 'replac':1426,1862,1869 'requir':73,118,227,668,1238,1512,1728 'restrict':305,1108 'retent':91,1470,1989 'reusabl':872 'review':44,125 'rewrit':1820,1833 'rls':42,116 'roi':207 'roll':1793 'rollback':142,355,1798 'room':1227,1237 'round':347 'row':89,402,426,1047,1056,1088,1186,1381,1401,1604,1632,1638 'row-level':1046 'row-loc':1185 'rule':154 'run':1788,1814 'safe':131,1040,1779,1800 'safeti':132 'scalar':2103 'scale':47,87,120 'scan':1303 'schedul':767 'schema':7,30,70,151,1780 'scheme':774 'scope':1024 'scratch':1032 'search':820,826,830,937,1335,1361,1917,2010 'secur':1049,1058 'select':33,1068 'selective/frequently':1281 'semant':226 'separ':1563,1571,1601 'sequenc':364 'sequences/identity':348 'seri':171,1375,1433,1986 'serial':1005 'server/mysql':389 'session':1023 'session-scop':1022 'set':576,583,677,1109,1111 'signatur':1858 'silent':322,344 'similar':936,1920,2009 'simpl':1978 'singl':851,1637 'single-argu':850 'single-row':1636 'skill':26,54 'skill-postgresql' 'slice':731 'slow':1625 'small':675 'smaller':480 'smaller/faster':2071 'smallint':483 'snake':287 'source-sickn33' 'space':475,494,1581 'spatial':808,817 'special':1557 'specif':6,997,1180,2102 'specifi':837,1103 'speed':1119 'sql':388,2210,2253,2316 'stabl':676,1610 'stage':147,1644 'standard':1156 'start':646 'state':665,680 'status':694,1312,1321,1326,2059,2061,2275,2282 'storag':381,474,493,539,577,1377 'store':533,1882,1895,2130,2341 'strategi':578 'street':887 'string':262,503,1979 'strings/binary':528 'structur':894 'subsequ':400 'subset':1310 'supersed':1972 'support':758,797,1554,1996,2091,2097 'surrog':1714 'syntax':744,902 'system':448 'tabl':22,45,161,571,581,702,741,880,1014,1053,1306,1399,1415,1442,1537,1552,1562,1572,1641,1700,1797,1835,1847,2117,2182,2212,2255,2318 'table/column':290 'tag':734,2169 'target':58,88,586,1733 'task':1419 'tbl':572,582,1054,1289,1317,1340,2031,2079,2118,2134 'temporari':1021 'test':1801 'text':260,505,696,704,819,825,868,888,890,892,968,1360,1916,1933,1964,2224,2229,2276,2335 'theme':2334,2340 'three':1195 'three-valu':1194 'threshold':531,589 'time':170,256,626,647,655,952,1374,1432,1462,1985 'time-bas':1461 'time-seri':169,1373,1431,1984 'time/date':1410 'time/hash':1663 'timescaledb':1459,1667,1981 'timestamp':629,639,649,950,1687 'timestamptz':253,627,956,986,991,1000,2234,2298 'timetz':982 'timezon':641 'toast':535,538,542,584 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'total':2287,2294 'trade':2088 'trade-off':2087 'transact':359,645,1139,1782,1790,1816 'tree':1100,1146,1247,2111,2148 'trgm':1914 'tri':375,664 'tri-stat':663 'trigger':1556 'truncat':329,345 'tsqueri':828,845 'tstzrang':755 'tsvector':821,833,840 'tune':68 'tupl':416,585 'type':13,35,95,429,671,752,784,801,863,874,882,884,929,931,946,974,983,1006,1015,1241,1934,1955,2000 'typeof':2205 'uniqu':292,294,299,1093,1141,1542,1693,1729,1742,2227,2240 'uniqueness/opacity':187 'unless':409,473,484,492,611,662,1151,1178,1941 'unlik':340,387 'unlog':1034,1640 'unquot':280 'updat':199,1560,1568,1584,1590,1596,1599,1603,1759,1773,1777 'update-heavi':1559 'updates/deletes':413 'upsert':1725 'upsert-friend':1724 'us':679,1487,1490 'us-east':1486 'us-west':1489 'use':24,52,144,175,182,228,286,298,458,465,497,510,522,596,604,642,695,707,739,776,849,910,916,942,949,955,960,967,972,976,981,985,990,999,1004,1008,1072,1129,1222,1225,1259,1269,1329,1395,1412,1413,1536,1555,1576,1627,1677,1749,1976,2032,2080,2145,2164,2183,2188,2349 'user':162,1063,1071,1073,1076,1082,1318,1503,2209,2213,2214,2243,2249,2266,2272,2273,2307,2320,2326,2327 'user-bas':1081 'user@example.com':1353 'usual':566 'uuid':183,442,463,1723,1832,1903,1906 'uuid-ossp':1902 'uuidv7':455 'v':2041 'vacuum':417 'val1':745,749 'val2':746,750 'valid':109,148,876 'valu':233,266,666,691,870,1190,1196,1221,1450,1477,1484,1757,1969,2194 'varchar':517,964 'vector':928,930,935,2008 'version':469,768,853,1872 'virtual':1889 'visit':1305 'volatil':1817,1826,1838 'wall':653 'wall-clock':652 'week':683 'west':1491 'wide':425 'wide-row':424 'within':896 'without':69,138,640,951,1304,2159 'work':1033,1748 'workload':1615,2064 'would':1754 'would-be-insert':1753 'write':1042,1648,1766,1810 'zip':891 'zone':953","prices":[{"id":"1ba3e95a-0529-40b7-b3de-4915aef59f7e","listingId":"b4343c6a-7c42-488c-9b46-5b81d6ebf222","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:42:34.861Z"}],"sources":[{"listingId":"b4343c6a-7c42-488c-9b46-5b81d6ebf222","source":"github","sourceId":"sickn33/antigravity-awesome-skills/postgresql","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/postgresql","isPrimary":false,"firstSeenAt":"2026-04-18T21:42:34.861Z","lastSeenAt":"2026-04-23T00:51:24.508Z"}],"details":{"listingId":"b4343c6a-7c42-488c-9b46-5b81d6ebf222","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"postgresql","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34616,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-22T06:40:00Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"04f5c13c5d3cb4d156f69a4d40692c422e940e9e","skill_md_path":"skills/postgresql/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/postgresql"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"name":"postgresql","description":"Design a PostgreSQL-specific schema. Covers best-practices, data types, indexing, constraints, performance patterns, and advanced features"},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/postgresql"},"updatedAt":"2026-04-23T00:51:24.508Z"}}