Integer

Learn about PostgreSQL integer data types — SMALLINT, INTEGER, and BIGINT — including storage sizes, value ranges, and how to choose the right type for your use case.

4 min read · Last updated: March 2026 · Back to overview

Quick Answer

PostgreSQL provides three integer types: SMALLINT (2 bytes, ±32,767), INTEGER (4 bytes, ±2.1 billion), and BIGINT (8 bytes, ±9.2 quintillion). Use INTEGER for most cases; use BIGINT only when values may exceed 2.1 billion.

Spin up a Postgres database in 20 seconds with Vela.

Try Vela Sandbox

PostgreSQL provides three integer types for storing whole numbers: SMALLINT, INTEGER, and BIGINT. Choosing the right type balances storage efficiency, value range, and query performance.

Integer type comparison

  • SMALLINT: 2 bytes — range -32,768 to +32,767. Good for small enumerations, ages, page counts.
  • INTEGER (INT, INT4): 4 bytes — range -2,147,483,648 to +2,147,483,647. The default choice for most integer columns.
  • BIGINT (INT8): 8 bytes — range -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807. Use only when INTEGER range is insufficient.

Note: PostgreSQL does not support unsigned integers. Use a CHECK constraint to enforce non-negative values when needed.

SMALLINT: page counts and small ranges

CREATE TABLE books (
  book_id SERIAL PRIMARY KEY,
  title   VARCHAR(255) NOT NULL,
  pages   SMALLINT NOT NULL CHECK (pages > 0)
);

The CHECK (pages > 0) constraint ensures only positive page counts are accepted, complementing the type's range limitation.

INTEGER: city populations and general use

CREATE TABLE cities (
  city_id    SERIAL PRIMARY KEY,
  city_name  VARCHAR(255) NOT NULL,
  population INT NOT NULL CHECK (population >= 0)
);

INT is a synonym for INTEGER. The 4-byte range covers over 2 billion — sufficient for most real-world integer values.

BIGINT: large-scale counters and IDs

CREATE TABLE events (
  event_id   BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  event_name VARCHAR(255) NOT NULL,
  occurred_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

Use BIGINT for primary keys on tables expected to grow beyond ~2 billion rows, or for storing Unix timestamps in milliseconds.

Production tips

  • Default to INTEGER for new columns — it covers nearly all practical integer values with minimal storage.
  • Use BIGINT proactively for auto-increment primary keys on high-volume tables to avoid painful migrations later when INTEGER hits its limit.
  • Use SMALLINT only when storage is a genuine concern and the value is provably bounded — for example, days of the week (0–6) or HTTP status codes.
  • PostgreSQL does not support unsigned integers — enforce non-negative constraints with CHECK (col >= 0) where needed.

Reference: PostgreSQL documentation — Integer Types.

Continue in PostgreSQL Data Types: SERIAL Data Type.

Related in this section: Boolean · CHAR, VARCHAR, and TEXT · NUMERIC

Frequently Asked Questions

What are the PostgreSQL integer types and their ranges?

PostgreSQL has three integer types: SMALLINT (2 bytes, -32,768 to +32,767), INTEGER or INT (4 bytes, -2,147,483,648 to +2,147,483,647), and BIGINT (8 bytes, -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807). All three store whole numbers only.

Is INT the same as INTEGER in PostgreSQL?

Yes. INT and INTEGER are identical synonyms in PostgreSQL. Both refer to the 4-byte signed integer type. INT4 is another alias for the same type.

Does PostgreSQL support unsigned integers?

No. Unlike MySQL, PostgreSQL does not have unsigned integer types. All integer types are signed. If you need to store only non-negative values, use a CHECK constraint: CHECK (quantity >= 0).

When should I use BIGINT instead of INTEGER?

Use BIGINT when values may exceed approximately 2.1 billion (the upper limit of INTEGER). Common cases include auto-increment primary keys on very large tables, Unix timestamps in milliseconds, or row counts for big data workloads. BIGINT uses 8 bytes vs INTEGER's 4 bytes, so avoid it when the extra range is not needed.

What happens if I store a value outside the range of an integer type?

PostgreSQL raises an error: "integer out of range". For example, inserting 32768 into a SMALLINT column fails. Preventing this requires choosing the right type upfront or migrating to a wider type when the limit is approached.