PostgreSQL supports three primary character data types: CHAR(n), VARCHAR(n), and TEXT. Unlike some other database systems, all three are stored identically under the hood — the difference is purely in length enforcement behavior.
Character type comparison
- CHARACTER(n) / CHAR(n): Fixed-length, blank-padded. Strings shorter than n are padded with spaces. Strings longer than n cause an error (except for excess trailing spaces, which are silently truncated).
- CHARACTER VARYING(n) / VARCHAR(n): Variable-length with an upper limit of n characters. Inserting a string longer than n raises an error.
- TEXT / VARCHAR (no length): Variable-length with no upper limit. Both are identical in behavior and performance.
Practical example: length enforcement
CREATE TABLE character_tests (
id serial PRIMARY KEY,
x CHAR(1),
y VARCHAR(10),
z TEXT
);
Trying to insert a 3-character string into x CHAR(1) raises an error:
INSERT INTO character_tests (x, y, z)
VALUES ('Yes', 'test', 'This is a long text column');
-- ERROR: value too long for type character(1)
Similarly, a string longer than 10 characters in y VARCHAR(10) raises an error:
INSERT INTO character_tests (x, y, z)
VALUES ('Y', 'This is a test for varchar', 'Long text here');
-- ERROR: value too long for type character varying(10)
A valid insert:
INSERT INTO character_tests (x, y, z)
VALUES ('Y', 'varchar(n)', 'This is a very long text for the PostgreSQL text column')
RETURNING *;
id | x | y | z
----+---+------------+---------------------------------------------------------
1 | Y | varchar(n) | This is a very long text for the PostgreSQL text column
Choosing the right character type
In most cases, use TEXT or VARCHAR (without a length). Only use VARCHAR(n) when you want PostgreSQL to actively enforce a maximum string length as a data integrity rule — for example, a 2-character ISO country code or a 10-digit phone number field.
Avoid CHAR(n) in new designs — the blank-padding behavior is rarely useful and can cause subtle comparison bugs.
Production tips
- Prefer
TEXTfor general-purpose string columns — it avoids unnecessary length restrictions that often become migration pain points later. - Use
VARCHAR(n)as a constraint, not a performance optimization — PostgreSQL has no storage advantage for shorter types. - Add a
CHECKconstraint for complex validation (e.g.,CHECK (char_length(code) = 2)) instead of relying solely onCHAR(2). - Casting a string to
CHAR(n)orVARCHAR(n)truncates it to n characters — useful for enforcing length at insert without raising an error, but use with care.
Reference: PostgreSQL documentation — Character Types.