jsonbArraysRangesUUIDEnumsConstraintsNormalizationPartitioning

Data Types & Schema Design

PostgreSQL's type system is one of its most underused strengths. Master jsonb, arrays, ranges, and the schema design decisions that are expensive to change after launch.

40 min read9 sections
01

Numeric & Character Types

Choosing the right numeric type matters for storage, performance, and correctness. The most common mistake is using numeric wheninteger suffices, or double precision for money.

TypeSizeRange / Use Case
smallint2 bytes-32,768 to 32,767 — status codes, small counters
integer4 bytes-2.1B to 2.1B — the default choice for most IDs and counts
bigint8 bytes-9.2×10¹⁸ to 9.2×10¹⁸ — large tables, snowflake IDs
numeric(p,s)variableExact decimal — money, financial calculations
real4 bytes6 decimal digits — scientific data where inexactness is OK
double precision8 bytes15 decimal digits — never use for money
serial / bigserial4 / 8 bytesAuto-increment shorthand (creates a sequence)

Never Use float for Money

0.1 + 0.2 = 0.30000000000000004 in floating point. For any financial calculation, use numeric(precision, scale)or store amounts as integers in the smallest unit (cents, paise).

Character Types

TypeBehaviorRecommendation
textVariable length, no limit✅ The default choice — use this
varchar(n)Variable length with limitRarely better than text + CHECK
char(n)Fixed length, space-padded❌ Almost never the right choice

In PostgreSQL, text and varchar have identical performance. The length check in varchar(n) adds a constraint but no storage benefit. Prefer text with a CHECKconstraint if you need length validation — it's easier to modify later.

1 / 9