← back to the generator

Table naming guide

Everything worth knowing about naming database tables: the rules the whole industry roughly agrees on, the one big debate nobody agrees on, and the patterns for join tables, history tables and columns.

The rules everyone agrees on

snake_case, lowercase, always

Use lowercase letters with underscores: user_accounts, line_items. PostgreSQL folds unquoted identifiers to lowercase, MySQL is case-sensitive on Linux, and mixed case forces quoting. Lowercase snake_case needs no quoting anywhere.

Descriptive, not clever

order_details beats data and tbl_1. A table name should tell the next developer what rows live inside without opening the schema. Avoid abbreviations nobody agreed on — expires_at, not exp.

No reserved words, ever

order, user, table, group, select and index are reserved in at least one major engine. Naming a table order means quoting it in every query forever. Pick orders or customer_orders instead.

Skip the tbl_ prefix

The table context is always known in a query, so tbl_users adds noise without information. Prefixes only pay off on chaotic shared servers — and even there, a schema name does the job better.

The one big debate

Plural (users) or singular (user)? The plural camp — Rails, Django, most style guides — argues a table holds many rows, so the collection name fits. The singular camp argues SELECT * FROM user reads naturally and matches the model class name. Both are defensible; mixing them is not. We gave the debate its own page: singular vs plural table names.

Join tables and relationships

Many-to-many tables combine both sides in alphabetical order so the name is predictable: categories_products, organization_users. Some frameworks use the singular pivot style instead — role_user. Either way, alphabetical ordering eliminates the "was it users_roles or roles_users?" guessing game. Our generator's join-table mode mints these pairs automatically.

Columns ride along

Table naming sets the tone for the whole schema. The conventions that pair with it:

Column cheat sheet

Columns are singular snake_case: first_name, email. Primary key is id. Foreign keys are singular_table_id — user_id on the orders table. Booleans start with is_ or has_ (is_active). Timestamps end with _at (created_at, updated_at). Never repeat the table name in its own columns — users.name, not users.user_name.

History, log and archive tables

Suffixes earn their keep for table variants: orders_archive, price_history, api_request_log. The base name stays recognizable and the suffix says what the variant is for. This is one of the few places a suffix beats a separate naming scheme.

Ready to mint some? Hit the free table name generator, or browse table name examples for full schemas you can steal.