# PostgreSQL Naming Conventions Standardized naming rules for all database objects in RelSpec PostgreSQL output. ## Quick Reference | Object Type | Prefix | Format | Example | | ----------------- | ----------- | ---------------------------------- | ------------------------ | | Primary Key | `pk_` | `pk__` | `pk_public_users` | | Foreign Key | `fk_` | `fk_
_` | `fk_posts_users` | | Unique Constraint | `uk_` | `uk_
_` | `uk_users_email` | | Unique Index | `uidx_` | `uidx_
_` | `uidx_users_email` | | Regular Index | `idx_` | `idx_
_` | `idx_posts_user_id` | | Check Constraint | `chk_` | `chk_
_` | `chk_users_age_positive` | | Sequence | `identity_` | `identity_
_` | `identity_users_id` | | Trigger | `t_` | `t__
` | `t_audit_users` | | Trigger Function | `tf_` | `tf__
` | `tf_audit_users` | ## Naming Rules by Object Type ### Primary Keys **Pattern:** `pk__
` - Include schema name to avoid collisions across schemas - Use lowercase, snake_case format - Examples: - `pk_public_users` - `pk_audit_audit_log` - `pk_staging_temp_data` ### Foreign Keys **Pattern:** `fk_
_` - Reference the table containing the FK followed by the referenced table - Use lowercase, snake_case format - Do NOT include column names in standard FK constraints - Examples: - `fk_posts_users` (posts.user_id → users.id) - `fk_comments_posts` (comments.post_id → posts.id) - `fk_order_items_orders` (order_items.order_id → orders.id) ### Unique Constraints **Pattern:** `uk_
_` - Use `uk_` prefix strictly for database constraints (CONSTRAINT type) - Include column name for clarity - Examples: - `uk_users_email` - `uk_users_username` - `uk_products_sku` ### Unique Indexes **Pattern:** `uidx_
_` - Use `uidx_` prefix strictly for index type objects - Distinguished from constraints for clarity and implementation flexibility - Examples: - `uidx_users_email` - `uidx_sessions_token` - `uidx_api_keys_key` ### Regular Indexes **Pattern:** `idx_
_` - Standard indexes for query optimization - Single column: `idx_
_` - Examples: - `idx_posts_user_id` - `idx_orders_created_at` - `idx_users_status` ### Check Constraints **Pattern:** `chk_
_` - Describe the constraint validation purpose - Use lowercase, snake_case for the purpose - Examples: - `chk_users_age_positive` (CHECK (age > 0)) - `chk_orders_quantity_positive` (CHECK (quantity > 0)) - `chk_products_price_valid` (CHECK (price >= 0)) - `chk_users_status_enum` (CHECK (status IN ('active', 'inactive'))) ### Sequences **Pattern:** `identity_
_` - Used for SERIAL/IDENTITY columns - Explicitly named for clarity and management - Examples: - `identity_users_id` - `identity_posts_id` - `identity_transactions_id` ### Triggers **Pattern:** `t__
` - Include purpose before table name - Lowercase, snake_case format - Examples: - `t_audit_users` (audit trigger on users table) - `t_update_timestamp_posts` (timestamp update trigger on posts) - `t_validate_orders` (validation trigger on orders) ### Trigger Functions **Pattern:** `tf__
` - Pair with trigger naming convention - Use `tf_` prefix to distinguish from triggers themselves - Examples: - `tf_audit_users` (function for t_audit_users) - `tf_update_timestamp_posts` (function for t_update_timestamp_posts) - `tf_validate_orders` (function for t_validate_orders) ## Multi-Column Objects ### Composite Primary Keys **Pattern:** `pk__
` - Same as single-column PKs - Example: `pk_public_order_items` (composite key on order_id + item_id) ### Composite Unique Constraints **Pattern:** `uk_
___[...]` - Append all column names in order - Examples: - `uk_users_email_domain` (UNIQUE(email, domain)) - `uk_inventory_warehouse_sku` (UNIQUE(warehouse_id, sku)) ### Composite Unique Indexes **Pattern:** `uidx_
___[...]` - Append all column names in order - Examples: - `uidx_users_first_name_last_name` (UNIQUE INDEX on first_name, last_name) - `uidx_sessions_user_id_device_id` (UNIQUE INDEX on user_id, device_id) ### Composite Regular Indexes **Pattern:** `idx_
___[...]` - Append all column names in order - List columns in typical query filter order - Examples: - `idx_orders_user_id_created_at` (filter by user, then sort by created_at) - `idx_logs_level_timestamp` (filter by level, then by timestamp) ## Special Cases & Conventions ### Audit Trail Tables - Audit table naming: `_audit` or `audit_` - Audit indexes follow standard pattern: `idx__` - Examples: - Users table audit: `users_audit` with `idx_users_audit_tablename`, `idx_users_audit_changedate` - Posts table audit: `posts_audit` with `idx_posts_audit_tablename`, `idx_posts_audit_changedate` ### Temporal/Versioning Tables - Use suffix `_history` or `_versions` if needed - Apply standard naming rules with the full table name - Examples: - `idx_users_history_user_id` - `uk_posts_versions_version_number` ### Schema-Specific Objects - Always qualify with schema when needed: `pk__
` - Multiple schemas allowed: `pk_public_users`, `pk_staging_users` ### Reserved Words & Special Names - Avoid PostgreSQL reserved keywords in object names - If column/table names conflict, use quoted identifiers in DDL - Naming convention rules still apply to the logical name ### Generated/Anonymous Indexes - If an index lacks explicit naming, default to: `idx__
` - Should be replaced with explicit names following standards - Examples (to be renamed): - `idx_public_users` → should be `idx_users_` ## Implementation Notes ### Code Generation - Names are always lowercase in generated SQL - Underscore separators are required ### Migration Safety - Do NOT rename objects after creation without explicit migration - Names should be consistent across all schema versions - Test generated DDL against PostgreSQL before deployment ### Testing - Ensure consistency across all table and constraint generation - Test with reserved words to verify escaping ## Related Documentation - PostgreSQL Identifier Rules: https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-IDENTIFIERS - Constraint Documentation: https://www.postgresql.org/docs/current/ddl-constraints.html - Index Documentation: https://www.postgresql.org/docs/current/indexes.html