Skip to main content

SQL Table Naming Dilemma: Singular vs. Plural

Adela · Oct 1, 2025

TL;DR: Pick one style, document it, and stick to it. If you're undecided, plural tables (users, orders) are a safe default: they read naturally in SQL and dodge a few reserved words. The consistency matters more than which side you land on.

Why it matters

A table name is not just a label. It shows up in your SQL, your ORM models, your migration files, your BI dashboards, and your docs. Once a row of code references users, renaming the table later means touching all of those places at once. So the convention you pick early tends to outlive whatever reasoning produced it. A consistent one lowers the cognitive load for everyone reading the schema and shortens the time it takes a new hire to find their way around.

The two camps

Singular (user, order_item)

Pros

  • OOP alignment: a table maps cleanly to a class or entity. One row is one User, so User.find(1) lining up with the user table feels right.
  • Language simplicity: you avoid irregular plurals, which is a real help for international teams who would otherwise have to guess at English pluralization rules.
  • Master-detail reads cleanly: order and order_detail sit naturally next to each other.

Cons

  • Reserved words: user, order, group, and session are reserved or near-reserved in several databases, so you end up quoting them or working around them.
  • Query feel: SELECT * FROM user reads a bit stilted, like you forgot the rest of the sentence.

Plural (users, order_items)

Pros

  • Natural language in SQL: SELECT * FROM users WHERE age > 21 reads the way you would say it out loud.
  • Reserved-word avoidance: orders is safer than order, groups safer than group.
  • Framework affinity: Rails pluralizes by default, and a lot of modern stacks follow the same convention, so plural tends to be the path of least resistance there.

Cons

  • Semantic mismatch: a row represents a single user but lives in a table called users, which can grate if you think in entities.
  • Irregulars: person/people and child/children introduce edge cases your pluralizer has to handle correctly.

Industry split (rule of thumb)

ApproachCommon InKey Advantage
SingularEnterprise / traditional systemsOOP consistency; entity focus
PluralWeb frameworks / modern stacksReadability; framework defaults

There's no universal standard; both conventions are widespread. What matters is a deliberate choice and consistency.

Quick decision guide

A few situations where one side has the clearer edge:

  • Greenfield and undecided: go plural. It's the lower-friction default in most modern toolchains.
  • Existing codebase: match what's already there. Mixing the two in one schema is worse than either choice on its own.
  • Reserved-word risk: prefer plural (orders, groups) to sidestep the quoting.
  • Strict DDD shops or heavy OOP mapping: singular can fit better, since your tables line up one-to-one with your entities.

Practical conventions (copy-paste)

If you want a concrete starting point rather than a debate, here's a set that holds up well:

  1. Tables: plural, snake_case, so users, orders, order_items, audit_logs.
  2. Join tables: plural plus plural, alphabetical, so orders_products, roles_users.
  3. Columns: singular, snake_case, so id, user_id, created_at, updated_at.
  4. Views and materialized views: prefix plus plural, so v_active_users, mv_daily_signups.
  5. Reference tables: plural, so countries, currencies, order_statuses.
  6. Irregular nouns: decide once (always people or always persons) and never relitigate it.

Master-detail naming tips

The master-detail pair is where the singular-vs-plural choice shows up most visibly:

  • Singular world: order and order_detail is tidy and reads well.
  • Plural world (the more common one): use orders and order_items. It keeps the collection metaphor intact. Avoid orders_details, and name the child after the object it holds (order_items) rather than reaching for "detail."

Governance (make it stick)

A convention only helps if it survives contact with a busy team, so put some scaffolding around it:

  • Write the rule down in your engineering handbook.
  • Add a schema linter or CI check that blocks drift before it merges.
  • Include examples for the cases people actually trip on: irregular plurals, join tables, reserved words.

Examples

Plural (recommended default)

CREATE TABLE users (
  id BIGSERIAL PRIMARY KEY,
  email TEXT UNIQUE NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE orders (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES users(id),
  status TEXT NOT NULL,
  total_cents INTEGER NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE TABLE order_items (
  order_id BIGINT NOT NULL REFERENCES orders(id),
  product_id BIGINT NOT NULL REFERENCES products(id),
  quantity INTEGER NOT NULL DEFAULT 1,
  PRIMARY KEY (order_id, product_id)
);

Singular (for strict entity alignment)

CREATE TABLE user (
  id BIGSERIAL PRIMARY KEY,
  email TEXT UNIQUE NOT NULL
);

CREATE TABLE order (
  id BIGSERIAL PRIMARY KEY,
  user_id BIGINT NOT NULL REFERENCES user(id)
);
/* Beware: user/order can conflict with reserved words in some contexts */

Final recommendation

Choose one convention, document it, and enforce it. If you don't have a strong reason to do otherwise, pick plural tables plus singular columns with snake_case, and stop reopening the debate in every PR. A schema that's consistently "wrong" by your taste is still easier to live with than one that's half right both ways.

Back to blog

Explore the standard for database development