Add Column in PostgreSQL

Learn how to use ALTER TABLE ADD COLUMN to add one or more columns to an existing PostgreSQL table, including the safe pattern for adding NOT NULL columns to populated tables.

4 min read · Back to overview

Quick Answer

Use ALTER TABLE table_name ADD COLUMN column_name data_type [constraint] to add a new column. Adding a nullable column or one with a constant default (PostgreSQL 11+) is a metadata-only operation. Adding NOT NULL to a non-empty table requires a default value or a separate backfill step.

Spin up a Postgres database in 20 seconds with Vela.

Try Vela Sandbox

ALTER TABLE ... ADD COLUMN extends an existing PostgreSQL table with one or more new columns. New columns are always appended at the end of the column list. Adding a nullable column (or a column with a constant default in PostgreSQL 11+) is a metadata-only operation that completes instantly even on very large tables.

Syntax

ALTER TABLE table_name
  ADD COLUMN column_name data_type [constraint];

Add multiple columns in one statement to minimize lock acquisitions:

ALTER TABLE table_name
  ADD COLUMN col1 data_type constraint,
  ADD COLUMN col2 data_type constraint;

Practical Example

Start with a minimal products table and extend it over time:

CREATE TABLE products (
  product_id  SERIAL PRIMARY KEY,
  sku         VARCHAR(50) NOT NULL UNIQUE,
  name        VARCHAR(200) NOT NULL
);

Add a single nullable column — instant, no table rewrite:

ALTER TABLE products ADD COLUMN description TEXT;

Add multiple columns at once:

ALTER TABLE products
  ADD COLUMN unit_price   NUMERIC(10,2) NOT NULL DEFAULT 0,
  ADD COLUMN is_active    BOOLEAN       NOT NULL DEFAULT TRUE,
  ADD COLUMN created_at   TIMESTAMPTZ   NOT NULL DEFAULT now();

Verify the updated structure:

\d products

Add a NOT NULL column to a table that already has rows — three-step pattern:

-- Step 1: add without NOT NULL (existing rows get NULL)
ALTER TABLE products ADD COLUMN supplier_code VARCHAR(20);

-- Step 2: populate existing rows
UPDATE products
SET supplier_code = 'UNKNOWN'
WHERE supplier_code IS NULL;

-- Step 3: enforce NOT NULL
ALTER TABLE products ALTER COLUMN supplier_code SET NOT NULL;

Confirm the constraint is in place:

SELECT column_name, is_nullable
FROM information_schema.columns
WHERE table_name = 'products'
  AND column_name = 'supplier_code';

Performance Characteristics

ScenarioTable rewrite?Lock duration
Nullable column (no default)NoMilliseconds
Constant default, PG 11+NoMilliseconds
Volatile default (e.g., now())YesMinutes on large tables
NOT NULL without default on empty tableNoMilliseconds
NOT NULL without default on populated tableError

Testing with Vela

When adding columns to large, heavily trafficked tables, Vela database branching lets you test each migration step on a production-sized clone: measure lock duration, verify the backfill UPDATE, and confirm the SET NOT NULL validation pass before running against the live database.

Production Tips

  • Adding a nullable column is safe and instant — it does not rewrite the table or block reads beyond the brief lock acquisition.
  • Adding a column with a constant (non-volatile) default is also metadata-only in PostgreSQL 11+ and does not require a table rewrite.
  • Never add a NOT NULL column directly to a non-empty table without a default — follow the three-step add, backfill, constrain pattern.
  • Use a single ALTER TABLE with multiple ADD COLUMN clauses to minimize lock acquisitions when adding several columns at once.
  • PostgreSQL appends new columns at the end of the column list. Control display order in SELECT statements rather than relying on physical column order.

Continue in Managing Tables: Drop Column.

Related in this section: PostgreSQL Data Types · Create Table · Select Into

Frequently Asked Questions

What does ALTER TABLE ADD COLUMN do in PostgreSQL?
ADD COLUMN appends a new column definition to an existing table. For nullable columns (and constant-default columns in PG 11+), it is a metadata-only operation that completes instantly without rewriting the table. Existing rows see NULL for the new column unless a default is set.
Does ADD COLUMN lock the table and block queries?
ADD COLUMN acquires a brief ACCESS EXCLUSIVE lock. For nullable columns and constant-default columns (PG 11+), the lock is held for only a fraction of a second because no table rewrite is needed. Adding a column with a volatile default (e.g., now()) still requires a table rewrite and holds the lock for much longer.
What happens to existing rows when I add a column with a default value?
In PostgreSQL 11+, adding a column with a constant default is metadata-only. Existing rows transparently return the default value without being physically rewritten. For volatile defaults (e.g., now()), PostgreSQL rewrites all rows to store the expression's result at the time of the ALTER TABLE.
Can I specify the position of a new column?
No. PostgreSQL always appends new columns at the end of the column list. If column order matters for display, control it in your SELECT statements with an explicit column list.
What is the safest way to add a NOT NULL column to a large production table?
Follow the three-step pattern: (1) add the column without NOT NULL, (2) backfill existing rows with UPDATE, (3) apply SET NOT NULL once all rows have a value. Each step takes a brief lock, avoiding the long rewrite that a direct NOT NULL addition would require.