← All 55 books PostgreSQL starters, one command per page Get the full edition · £10
One command per page

PostgreSQL starters, one command per page

Thirty-two steps for developers who know some SQL and have just been handed a Postgres database: the server and its client processes, createdb, databases holding schemas holding tables, the search path, psql and its backslash commands, BEGIN and COMMIT, savepoints, the MVCC snapshot model, VACUUM and the autovacuum daemon, EXPLAIN and EXPLAIN ANALYZE, the index types B-tree, GIN and BRIN, index-only scans, json and jsonb, roles and GRANT, and pg_dump with pg_restore, one command per page.


Steve Hodgkiss 7 steps

A diagram, the classic trap, and one command to go try this week. That's a page.

PostgreSQL starters, one command per page

Thirty-two steps for developers who know some SQL and have just been handed a Postgres database: the server and its client processes, createdb, databases holding schemas holding tables, the search path, psql and its backslash commands, BEGIN and COMMIT, savepoints, the MVCC snapshot model, VACUUM and the autovacuum daemon, EXPLAIN and EXPLAIN ANALYZE, the index types B-tree, GIN and BRIN, index-only scans, json and jsonb, roles and GRANT, and pg_dump with pg_restore, one command per page.


Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).

PostgreSQL behaviour checked against the PostgreSQL 18 official documentation (postgresql.org/docs/current, PostgreSQL 18.6, released 2026-08-13), fetched and read during this build: Tutorial chapters 1 and 3 (Architectural Fundamentals, Creating a Database, Transactions); DDL chapters 5.8 and 5.10 (Privileges, Schemas); Concurrency Control 13.1 (Introduction); Indexes 11.2 and 11.9 (Index Types, Index-Only Scans); Data Types 8.14 (JSON Types); Chapter 21 (Database Roles); Maintenance 24.1 (Routine Vacuuming); Backup and Restore 25.1 (SQL Dump); the SQL commands EXPLAIN, GRANT, VACUUM; and the psql, pg_dump and pg_restore reference pages. Concepts are named as the documentation names them. Teaching conventions (one command a day) are named as conventions. This book quotes no verbatim passages and is an independent guide not affiliated with or endorsed by the PostgreSQL Global Development Group. PostgreSQL is a trademark of the PostgreSQL Community Association of Canada.

General information only. Not professional advice; verify against your own PostgreSQL version and the current documentation.

Your purchase is for personal use only. You do not have redistribution rights: please do not share, resell, or republish this book or its pages.

© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.

Edition 1.0 · stevehodgkiss.net

Contents

Contents


Part 1 · The model4
One server, many clients5
Databases hold schemas6
psql, the front door7
Part 2 · Safe changes8
BEGIN and COMMIT9
Reading never blocks writing10
Part 3 · Keeping it fast
The heap and the index11
Part 4 · Your data's shape
One cluster, one tree12
Part 1 of 4
Server, databases, psql
1

The model

What Postgres is: a server process with one process per connection, databases holding schemas holding tables, the public schema and the search path, and psql, the terminal front door to all of it.


In this part
  1. 01One server, many clients
  2. 02Databases hold schemas
  3. 03psql, the front door

PostgreSQL uses a client/server model. A server process, which manages the database files, accepts connections from client applications and performs database actions on their behalf. The server program is called postgres. The server forks a new process for each connection; the supervisor stays running while client and server processes come and go. Per the PostgreSQL 18 documentation, 1.2 Architectural Fundamentals.

PostgreSQL starters · No. 01
The model

One server, many clients

postgres the server, psql the client

ONE SERVER, MANY CLIENTSpsqlmydb=# _web appyour code, connectingGUI toolpgAdmin, DBeaverclientscome and gopostgresone processper connectionpostgres manages the files, accepts connections, does the work

Let's say you've just typed psql and you're in. Worth knowing what actually happened.

There was already a server process running, called postgres. It manages the database files. Your psql is a client: it connects, and the server forks a whole new process just for your connection. Clients come and go, even from another machine. The server stays.

psql is just a client. postgres is the house.

TRY THIS WEEK

Connect with psql this week and run SELECT version();. You just spoke to the server.

A database contains one or more named schemas, which in turn contain tables. Schemas also contain other named objects, including data types and functions. Within one schema, two objects of the same type cannot have the same name; the same name can be used in different schemas without conflict. Each database contains a public schema and a pg_catalog schema holding the system tables and built-in types, functions and operators. Per the PostgreSQL 18 documentation, 5.10 Schemas.

PostgreSQL starters · No. 02
The model

Databases hold schemas

And schemas hold your tables

DATABASES HOLD SCHEMASpostgresthe serverdatabase: salesdatabase: mydbmydbpublicmyschemausersordersstaging.usersaudit.eventsschemas are notwalls: any schemayou have rights onis reachablesame name, two schemasno conflictdatabase, then schema, then table: three levels

Let's say you came from MySQL and your database.table habit just broke. It breaks one level deeper here.

A database contains schemas, and schemas hold tables, types and functions. Every database starts with a public schema, where your tables land by default, and a pg_catalog schema for the system tables and built-ins. Schemas aren't walls: you can reach any one you have privileges on.

Database, then schema, then table. Three levels.

TRY THIS WEEK

In psql this week, run SELECT schema_name FROM information_schema.schemata; and list the schemas in your database.

psql is a terminal-based front-end to PostgreSQL. It enables you to type in queries interactively, issue them to the server and see the results. Input can be from a file or command line arguments. psql provides a number of meta-commands and various shell-like features for scripting. Per the PostgreSQL 18 documentation, the psql reference page.

PostgreSQL starters · No. 03
The model

psql, the front door

Two languages in one prompt

PSQL, THE FRONT DOORpsqlmydb=SELECT ...;\dtmeta-commandpostgresSQL goes to the serverpsql keeps this onepsql -c 'SELECT 1;'psql -f import.sqlno mixing SQL and metain one single -cSQL to the server. Backslash to psql.

Let's say you've been pasting SQL into a GUI and someone hands you a server with only a terminal.

psql is the terminal front-end: you type queries, the server runs them, you see results. But psql speaks two languages. SQL goes to the server. Backslash meta-commands, psql keeps for itself, for navigating and scripting. -c runs one command string and exits. -f reads commands from a file. One rule from the docs: you can't mix SQL and meta-commands in a single -c, because -c must be completely parsable by the server.

SQL to the server. Backslash to psql.

TRY THIS WEEK

Run psql -c 'SELECT 1;' this week: one command, straight in, straight out.

Part 2 of 4
Transactions, snapshots
2

Safe changes

Bundling steps into all-or-nothing work: BEGIN and COMMIT, ROLLBACK, savepoints for part-way mistakes, and the snapshot model underneath it where readers never block writers.


In this part
  1. 01BEGIN and COMMIT
  2. 02Reading never blocks writing

A transaction bundles multiple steps into a single all-or-nothing operation. In PostgreSQL, a transaction is set up by surrounding the SQL commands with BEGIN and COMMIT. The intermediate states are not visible to other concurrent transactions, and if a failure prevents completion, none of the steps affect the database at all. Without an explicit BEGIN, each statement gets an implicit BEGIN and COMMIT wrapped around it. Per the PostgreSQL 18 documentation, 3.4 Transactions.

PostgreSQL starters · No. 04
Safe changes

BEGIN and COMMIT

All of it lands, or none of it does

BEGIN AND COMMITTRANSACTIONUPDATE accounts ...UPDATE accounts ...other sessions seeno middle stateCOMMIT;the databaseboth rows landwindow closed earlynothing landedeach statement alone = its own implicit BEGIN and COMMIT

Let's say the migration takes money from one row and adds it to another, and only one of those may ever happen.

Wrap the steps in BEGIN and COMMIT and they become one transaction: atomic. Other sessions can't see the middle, and if anything fails partway, none of it lands. Without a BEGIN, every statement is its own tiny transaction; the docs say each gets an implicit BEGIN and COMMIT. The trap is quiet: open a transaction, forget the COMMIT, close the window. The work vanishes with it.

Either all of it lands, or none of it does.

TRY THIS WEEK

In psql this week: BEGIN;, run one UPDATE, then quit with \q before COMMIT. Reconnect and check that nothing happened.

PostgreSQL maintains data consistency by using a multiversion model, Multiversion Concurrency Control, MVCC. Each SQL statement sees a snapshot of data as it was some time ago, regardless of the current state of the underlying data. Locks acquired for reading do not conflict with locks acquired for writing: reading never blocks writing and writing never blocks reading. Per the PostgreSQL 18 documentation, 13.1 Introduction.

PostgreSQL starters · No. 05
Safe changes

Reading never blocks writing

The MVCC snapshot model

READING NEVER BLOCKS WRITINGreadera long reportwritera busy importevents (the table)row 41 oldrow 41 oldrow 19new versionappendedbelowsnapshotas it wassome time agono lockbetween the twoMVCC: multiversionconcurrency control

Let's say the nightly report runs for an hour and you've been told never to write during it. In Postgres, write anyway.

Consistency comes from MVCC: each statement sees a snapshot of the data as it was some time ago, not a lock on the present. Readers read their snapshot; writers add new versions; neither waits. Reading never blocks writing, and writing never blocks reading.

Reading never blocks writing. That's the model.

TRY THIS WEEK

In one psql session this week run BEGIN; then a SELECT, leave it open, and INSERT from a second session. Both work.

All indexes in PostgreSQL are secondary indexes, stored separately from the table's main data area, which is called the table's heap. In an ordinary index scan, each row retrieval requires fetching data from both the index and the heap, and the heap-access portion involves random access, which can be slow. Per the PostgreSQL 18 documentation, 11.9 Index-Only Scans and Covering Indexes.

PostgreSQL starters · No. 06
Speed

The heap and the index

A signpost beside the city

THE HEAP AND THE INDEXa..fg..mn..st..zindexheap (the table's data area)pointers, not rowsrandomaccessevery index is secondary: stored apart from the heap

Let's say you added an index and the query still reads a lot. This is the picture that explains it.

Every index in Postgres is secondary: stored separately from the table's data area, which the docs call the heap. An index entry doesn't hold your row; it points at it. So an ordinary index scan fetches from both worlds, a walk down the index, then a lookup in the heap for each match. The docs call that heap portion a lot of random access, and it can be slow. That's also why the planner sometimes ignores your index: for enough matches, walking the heap directly is cheaper.

The index is a signpost. The heap is the city.

TRY THIS WEEK

EXPLAIN a query that filters on an indexed column this week and find Index Scan using, your index's name, in the plan.

The whole model in one place: a server process managing databases that contain schemas and tables, one process per connection, MVCC snapshots where reading never blocks writing, updates leaving old row versions for VACUUM, secondary indexes beside the heap, roles with privileges, and pg_dump for the copy that outlives the machine. Per the PostgreSQL 18 documentation, chapters 1, 5, 13, 21, 24 and 25.

PostgreSQL starters · No. 07
The long game

One cluster, one tree

Everything you met, one picture

ONE CLUSTER, ONE TREEpostgresschemas hold tablesmydbsalesusersordersdealsleadspublicpublica..fg..mn..st..zindexheapsignpost beside the cityrolesGRANTsnapshots: readers neverblock writers; VACUUM sweepswhat updates leave behindpg_dump mydbthe copy thatoutlives the machineserver, database, schema, table, heap, index: every page lives in this tree

Let's say someone asks what Postgres is, and you get one sentence.

One server, postgres, holding databases; each database holds schemas, and schemas hold tables, with indexes standing beside the heap like signposts beside a city. Every connection gets its own process. Every statement reads a snapshot, so readers never block writers, and VACUUM sweeps what updates leave behind. Roles own the objects, GRANT opens the doors, pg_dump keeps the copy that outlives the machine.

One server, many databases, one tree.

TRY THIS WEEK

Draw the tree from memory this week: server, database, schema, table, heap, index. Then check it against \l and \dt.

Index

Index


BEGIN and COMMIT9
Databases hold schemas6
One cluster, one tree12
One server, many clients5
psql, the front door7
Reading never blocks writing10
The heap and the index11