Published on Aug 9, 2026

Notes from The Art of PostgreSQL

8 min read·

Dimitri Fontaine's The Art of PostgreSQL makes the case that SQL is the most underused tool in a developer's toolkit. The book is aimed at application developers who use PostgreSQL through an ORM and argues you're leaving a lot on the table if you treat SQL as a fallback rather than a first-class tool. It is organised into 8 parts and 53 chapters, building from simple queries all the way through extensions like pgvector and pg_trgm.

Preface

Fontaine sets the tone with two quotes that frame the rest of the book.

Data dominates. If you've chosen the right data structures and organized things well, the algorithms will almost always be self-evident. Data structures, not algorithms, are central to programming.

  • Rob Pike, Notes on Programming in C (1989)

If you wish to count lines of code, you should not regard them as "lines produced" but as "lines spent."

  • Edsger W. Dijkstra, The Humble Programmer (1972)

SQL is one of the tools you have as a developer, and most developers use only a small fraction of what's possible - that's what the book is trying to fix.

Part 2: Introduction

Builds a simple dataset (the CIA Factbook retail sales data) and makes a comparison: twenty lines of Python versus one SQL query that computes the same thing.

Why PostgreSQL?

PostgreSQL is described as the "world's most advanced Open Source database." Fontaine is a Major Contributor, so this isn't an unbiased endorsement - but the case is still strong: rich data types, extensibility, advanced indexing, real concurrency control, and a query planner that gets smarter every release.

SQL Injection and Server-Side Prepared Statements

PREPARE/EXECUTE gives you both safety and a planning win: the query is parsed and planned once and reused.

Part 3: Writing SQL Queries

This is where the "SQL is code" thesis becomes practical.

Business Logic in SQL

Most business logic that lives in application code could be a single SQL query. Round-trips, hydration, and re-implementing aggregations in code cost time and introduce bugs.

The SQL REPL

psql is your REPL. Set up a .psqlrc so every connection gives you useful defaults (timing, null display, history). The book shows how to discover a schema interactively, build a reporting tool, and use psql as a query editor.

SQL Is Code

This chapter changed how I think about SQL files in a codebase.

Indexing Strategy

Index types PostgreSQL supports:

Variants include partial, covering, and functional indexes, plus fillfactor and HOT updates for write-heavy tables. Index for both constraints and query patterns, but every index has a write cost.

Part 4: SQL Toolbox

The SQL features most ORMs hide from you.

GROUP BY, HAVING, WITH, UNION ALL

The F1 world champions example query: one query, all champions since 1950, drivers and constructors, using GROUPING SETS and chained CTEs.

Understanding Nulls

Three-valued logic: true, false, unknown. NULL = NULL is not true. NOT NULL constraints are the cheapest correctness you can buy. Outer joins introduce nulls.

Window Functions

Frames, partitioning, ordering, and the difference between ROWS, RANGE, and GROUPS.

Understanding Relations and Joins

Relations are sets, not lists. Join types have specific output cardinality, and getting this wrong is where most query bugs come from.

Watch for silent row loss: joins can drop rows you expected to keep.

Part 5: Data Types

The rich type system PostgreSQL actually offers.

PostgreSQL Data Types

Denormalised Data Types

Range Types and Exclusion Constraints

A daterange column with an EXCLUDE constraint makes overlapping validity periods impossible at the schema level, not the application level.

Part 6: Data Modeling

Fontaine deliberately puts this late: you need to know SQL's capabilities before you can design a model that takes advantage of them.

Normalisation

Standard coverage of normal forms, but Fontaine keeps asking the practical question: does this model make my queries easy? The three database anomalies (update, insertion, deletion) frame the discussion.

Practical Use Case: Geonames

Takes a real dataset and builds a sensible schema around it: GiST indexing on geometry, timezone handling, feature classification.

Modelling Anti-Patterns

Denormalisation

Not Only SQL

JSONB makes "schemaless" design possible, but durability and consistency trade-offs still apply. Structured schema for the things you know, JSONB for the things you don't.

Part 7: Data Manipulation and Concurrency Control

DML and what actually happens when two writers show up.

Insert, Update, Delete

INSERT INTO ... SELECT for batch loads. MERGE (PG 15+) gives you upsert-with-delete in one statement. RETURNING gives back the rows you wrote, useful for triggers and ETL.

Isolation and Locking

PostgreSQL uses SSI (Serializable Snapshot Isolation), which gives you serialisable without the locking overhead of traditional approaches. Most of the time you want READ COMMITTED. When you don't, know what you're getting.

Computing and Caching in SQL

Views, materialised views, and the cache invalidation problem. The book argues you should think of caching as a database concern, not an application concern - the database already has the data and knows when it changes.

Triggers

Transactional event-driven processing. Anti-pattern: using triggers to maintain a counter on a parent row. It serialises writes against the parent.

Listen and Notify

PostgreSQL's built-in pub/sub. Useful for cache invalidation across processes and for decoupled event systems. Limitations: notifications are not durable, and you have to use a connection to listen.

Part 8: PostgreSQL Extensions

This is where Postgres becomes a platform rather than just a SQL database. CREATE EXTENSION installs packages of SQL objects, and Fontaine works through the notable ones across this part.

What's a PostgreSQL Extension?

A package of SQL objects (functions, types, operators, indexes) installed with CREATE EXTENSION. Fontaine lists the notable ones: bloom, earthdistance, hstore, ltree, pg_trgm, PostGIS, ip4r, citus, pg_partman, postgres-hll, RUM.

Auditing with hstore

A trigger records every change to a row as an hstore key/value diff, useful for audit trails without a separate schema or service.

Trigrams and Typos with pg_trgm

Fuzzy text matching built on similarity() and the % operator, both GIN-indexable - this is how you do "did you mean...?" search in PostgreSQL without bolting on Elasticsearch.

Geolocation with ip4r

IP address ranges as a first-class type with IP-to-location lookups via proper indexing.

Counting Distinct Users with HyperLogLog

Probabilistic distinct counts - fast, cheap, lossy when approximate is good enough.

Vector Search with pgvector

New in 2026. The vector type, distance operators (<=>, <->, <#>), IVFFlat and HNSW indexes, recall measurement. Plus a hybrid search example combining vector similarity with trigram fuzzy match using Reciprocal Rank Fusion.


SQL is application code. The database is part of your application, so version it, test it, review it. Most of the performance and complexity problems I've seen in production were SQL problems dressed up as application problems.

The four things that changed my query writing most: window functions, GROUPING SETS, range types with exclusion constraints, pg_trgm.