PostgreSQL-specific conventions on top of database-design-basics: naming, precise types (citext/jsonb/timestamptz), and RLS basics.
0 downloads · Used by 1 stacks
Link back to this module from your own README.
[](https://markdowners.com/m/markdowners/postgres-conventions)No discussions about this module yet.
Start a discussionApplies Database Design Basics@markdowners/database-design-basics specifically to PostgreSQL — its type system and extensions give you more precise tools than the generic rules alone cover.
snake_case for all identifiers (tables, columns, functions) — Postgres folds unquoted identifiers to lowercase, so mixed-case names silently require quoting everywhere forever once introduced; avoid the problem entirely by never using mixed case.modules, users), foreign key columns as <singular_referenced_table>_id (author_id referencing profiles), and junction tables as <table_a>_<table_b> in a consistent, alphabetically-or-logically fixed order.citext for case-insensitive unique text (usernames, emails) instead of text plus a manually lowercased comparison — it enforces the invariant at the type level instead of relying on every query remembering to lowercase both sides.timestamptz, never bare timestamp, for anything that records a real-world moment — timestamp silently discards timezone information, which becomes a bug the moment the app or its users span more than one timezone.jsonb (not json) for semi-structured data that needs querying or indexing — jsonb is binary-stored and indexable; json is stored as text and re-parsed on every access.enum types or a text plus CHECK constraint for closed sets — prefer CHECK when the set might grow, since altering a native enum type has historically had more operational friction around adding new values inside a transaction.WHERE status = 'published') when a query pattern only ever filters a large table down to a specific, common subset — it's smaller and faster than indexing the whole table for that access pattern.gin_trgm_ops) indexes for full-text or fuzzy/substring search (ILIKE '%term%') — a plain b-tree index cannot serve those query patterns at all.check (...), not an anonymous one) so a future constraint-violation error message is diagnosable instead of a cryptic auto-generated identifier.using (author_id = auth.uid())) — untested or overly permissive RLS policies are a common, hard-to-notice source of data leaks, since a missing policy fails differently depending on configuration and default-deny setup.EXPLAIN ANALYZE on any query suspected of being slow before guessing at an index — intuition about which index would help is wrong often enough that it's not worth skipping the actual query plan.
Comments (0)
Sign in to comment. Sign in
No comments yet. Be the first to add one.