PostgreSQL Training Curriculum

Most PostgreSQL tutorials
leave you confused.

certuvia teaches PostgreSQL differently. Every lab starts with a realistic scenario โ€” you discover why the command exists before you touch it. A live Linux environment with real PostgreSQL and four preloaded databases runs in your browser. All 104 labs are available; browse the complete curriculum below.

Browse Labs
104Total Labs
104Available Now
100%In-Browser VM
student@lab:~$EXAMPLE
student@lab:~$ psql -h localhost -U postgres -d beer_db
psql (18.6)
beer_db=# SELECT current_database(), current_user;
current_database | current_user
beer_db | postgres
(1 row)
beer_db=# โ–Š

Everything in one viewport

Lab steps on the left, terminal on the right. No tab-switching, no copy-pasting between windows. Complete each objective and watch the checkmarks fill in.

104
Labs
104
Available Now
100%
Scenario-First

3 certificates. 104 labs. One clear path.

๐ŸŸข1 โ€”SQL Developer

Design schemas, write queries, and manage data with confidence.

6 blocksยท28 labsยท10โ€“13 hrs
๐Ÿ”ต2 โ€”Database Administrator

Configure, monitor, back up, and recover PostgreSQL.

7 blocksยท38 labsยท15โ€“18 hrs
๐ŸŸฃ3 โ€”Performance Engineer

Diagnose slow queries, tune indexes, and scale PostgreSQL.

7 blocksยท38 labsยท18โ€“24 hrs
Block 1.1

Connecting & Orienting

The setup phase is where beginners lose confidence. These labs make the environment feel navigable before a single table is created.

Block 1.2

Your First Schema

DDL decisions are permanent and costly to reverse in production. Make each column choice count.

๐Ÿ—๏ธLab 1.2.120 min

CREATE TABLE and Data Types

Choose the right column type โ€” not everything is text or integer

Start lesson โ†’
๐Ÿ”’Lab 1.2.225 min

Constraints That Protect Your Data

Make invalid data impossible to insert โ€” NOT NULL, UNIQUE, CHECK, DEFAULT

Start lesson โ†’
๐Ÿ”—Lab 1.2.325 min

Foreign Keys and Referential Integrity

Link tables with REFERENCES โ€” make orphaned rows impossible

Start lesson โ†’
๐Ÿ”งLab 1.2.430 min

Altering Tables Safely

Add columns, change types, drop constraints โ€” and know which ones are dangerous

Start lesson โ†’
๐Ÿ“Lab 1.2.520 min

Schema Organisation

Namespace your tables, set search_path, and lock down public schema access

Start lesson โ†’
๐ŸŽฏLab 1.2.640 min

ENUM Types, Generated Columns & Numeric Precision

Fix invalid statuses, stale computed columns, and float rounding in one lab

Start lesson โ†’
Block 1.3

Querying Data

A query that returns wrong rows is worse than one that returns no rows. Precision over volume.

Block 1.4

Joining Tables

JOINs are where SQL becomes truly expressive. Watch row counts change โ€” that tells you more than any definition.

Block 1.5

Aggregating, Writing, and Transactions

COUNT rows, GROUP BY buckets, write data safely, and wrap changes in transactions that either fully commit or fully roll back.

Block 1.6

Advanced Data Types & Modern SQL Patterns

JSONB for flexible payloads, arrays for multi-valued columns, range types for intervals that cannot overlap, and full-text search for natural language queries โ€” all built into PostgreSQL without extra dependencies.

Block 2.1

Server Anatomy & Configuration

Understand how a PostgreSQL cluster is laid out on disk, how to read and tune its configuration, control who can connect and how, apply changes safely with reload vs restart, and manage the service with pg_ctl.

๐Ÿ—‚๏ธLab 2.1.120 min

Cluster Layout

Navigate the PGDATA directory tree โ€” where data files, WAL segments, config files, and sockets live

Start lesson โ†’
โš™๏ธLab 2.1.225 min

postgresql.conf Deep Dive

Read, understand, and tune PostgreSQL parameters through pg_settings โ€” and know which changes take effect immediately

Start lesson โ†’
๐Ÿ”Lab 2.1.330 min

pg_hba.conf: Who Can Connect

Read host-based authentication rules, add a new rule, upgrade an authentication method, and apply both with a zero-downtime reload

Start lesson โ†’
๐Ÿ”„Lab 2.1.420 min

Reload vs Restart

Know which configuration changes need a full restart and which take effect immediately โ€” and use pending_restart to verify

Start lesson โ†’
๐Ÿ–ฅ๏ธLab 2.1.530 min

Service Management and pg_ctl

Start, stop, reload, and inspect the PostgreSQL server process โ€” and diagnose, fix, and recover from a failed startup

Start lesson โ†’
Block 2.2

Roles, Privileges & Security

Design a least-privilege role hierarchy, close the PUBLIC-access gap, isolate tenants with row-level security, enforce encrypted connections, and understand what real audit logging requires.

๐Ÿ‘ฅLab 2.2.122 min

Roles, Users, and Role Inheritance

Design a role hierarchy with NOLOGIN group roles, INHERIT login roles, and auditable SET ROLE impersonation

Start lesson โ†’
๐Ÿ—๏ธLab 2.2.224 min

GRANT, REVOKE, and Default Privileges

Revoke the PUBLIC-access default, grant precise privileges to the analyst role, and make the fix apply to tables that do not exist yet

Start lesson โ†’
๐Ÿ›ก๏ธLab 2.2.326 min

Row-Level Security

Enforce tenant isolation at the database layer with ENABLE ROW LEVEL SECURITY and a USING policy โ€” no application bug can bypass it

Start lesson โ†’
๐Ÿ”’Lab 2.2.428 min

SSL and Encrypted Connections

Enable TLS, require encryption for an application role, and verify the active connection.

Start lesson โ†’
๐Ÿ“œLab 2.2.522 min

Extensions and pgaudit

Install the available pgAudit extension and compare its read auditing with log_statement=ddl.

Start lesson โ†’
Block 2.3

Backup & Recovery

Take logical and physical backups, restore precisely under pressure, migrate roles alongside data, and recover to an exact point in time โ€” every lab ends with a verified, successful restore.

๐Ÿ’พLab 2.3.120 min

Logical Backups with pg_dump

Dump schemas and tables in plain, custom, and directory formats โ€” and understand why -Fc is the default that scales

Start lesson โ†’
๐Ÿ”Lab 2.3.222 min

pg_restore Strategies

Restore exactly one table from a custom-format dump without touching anything else โ€” then compare a serial restore against a parallel one

Start lesson โ†’
๐ŸŒLab 2.3.324 min

pg_dumpall and Globals

Discover what pg_dump silently leaves behind, migrate roles with pg_dumpall --globals-only, and prove a role-dependent restore only works once globals exist

Start lesson โ†’
๐Ÿ“ฆLab 2.3.422 min

Physical Backups with pg_basebackup

Take a full streaming physical backup of the cluster, restore it to an alternate data directory, and start it as a second, independent, writable instance

Start lesson โ†’
โฑ๏ธLab 2.3.526 min

Point-in-Time Recovery (PITR)

Configure WAL archiving, take a base backup, and recover to the exact second before a destructive statement โ€” then promote the recovered cluster to writable

Start lesson โ†’
Block 2.4

Monitoring & Observability

Query the statistics collector to find hot tables, trace a live lock chain, measure real bloat, tune autovacuum per table, configure logs you can actually search, and read the cache and I/O system PostgreSQL exposes about itself.

๐Ÿ“ŠLab 2.4.120 min

The Statistics Collector

Find hot tables with pg_stat_user_tables, measure a real cache hit ratio, and catch a scoping gotcha in counter resets

Start lesson โ†’
๐Ÿ”’Lab 2.4.222 min

Long-Running Queries and Locks

Trace a live blocking chain with pg_blocking_pids(), then choose between pg_cancel_backend and pg_terminate_backend to resolve it

Start lesson โ†’
๐ŸŽˆLab 2.4.320 min

Table and Index Bloat

Measure real bloat with pgstattuple, watch VACUUM reclaim space without shrinking the file, and see why VACUUM FULL is the one that actually does

Start lesson โ†’
๐ŸงนLab 2.4.420 min

Autovacuum Behaviour and Tuning

Read the autovacuum trigger formula from pg_settings, override it for one high-churn table, and watch it fire faster than the cluster default

Start lesson โ†’
๐Ÿ“œLab 2.4.520 min

Log Analysis Without pgBadger

Configure slow-query logging and csvlog properly, discover pgBadger is not on this box, and build the same report by hand with grep and awk

Start lesson โ†’
๐Ÿง Lab 2.4.622 min

pg_buffercache & Cache Introspection

Look directly inside shared_buffers, catch PostgreSQL's ring-buffer protection for large scans in the act, and see why a bigger cache does not always mean more caching

Start lesson โ†’
๐Ÿ’ฝLab 2.4.720 min

pg_stat_io: I/O Breakdown

Break disk I/O down to the exact operation โ€” heap writes, WAL, and VACUUM โ€” instead of one undifferentiated number

Start lesson โ†’
Block 2.5

Replication Fundamentals

Understand exactly what streams over the replication protocol, build a hot standby from scratch, protect it with a replication slot, measure its lag precisely, and migrate a single table live with logical replication.

๐Ÿ“กLab 2.5.120 min

WAL and the Replication Protocol

Read the write-ahead log directly โ€” its current position, how much a workload generates, and which files are safe to remove

Start lesson โ†’
๐Ÿ”Lab 2.5.225 min

Setting Up Streaming Replication

Build a real hot standby from scratch with pg_basebackup -R, start it on port 5433, and confirm it streams

Start lesson โ†’
๐ŸŽฐLab 2.5.322 min

Replication Slots

Watch a replication slot hold WAL open for a disconnected standby, measure exactly how much is retained, and clean it up safely

Start lesson โ†’
โฑ๏ธLab 2.5.422 min

Monitoring Replication Lag

Create lag on demand, watch write_lag and replay_lag diverge, then use a deliberate delay as a real disaster-recovery safeguard

Start lesson โ†’
๐Ÿ”€Lab 2.5.525 min

Logical Replication

Migrate a single table live between two independent clusters with CREATE PUBLICATION and CREATE SUBSCRIPTION โ€” no full standby required

Start lesson โ†’
Block 2.6

Maintenance & Upgrades

Read VACUUM output line by line, reclaim real disk space safely, survive a connection storm, upgrade a live cluster, and build the runbook that keeps all of it from becoming an emergency again.

๐ŸงฝLab 2.6.122 min

VACUUM and ANALYZE Mechanics

Read a real VACUUM VERBOSE output line by line, and watch the visibility map change state before and after

Start lesson โ†’
๐Ÿ”จLab 2.6.222 min

VACUUM FULL and CLUSTER

Reclaim real disk space with VACUUM FULL, physically reorder a table with CLUSTER, and watch the AccessExclusiveLock block a second session

Start lesson โ†’
๐ŸšฐLab 2.6.322 min

Connection Pooling with PgBouncer

Hit this database's real connection ceiling head-on, then learn the tool built to absorb exactly that storm

Start lesson โ†’
โฌ†๏ธLab 2.6.425 min

Major Version Upgrade with pg_upgrade

Run a real pg_upgrade --check, then a real --link upgrade, and verify every database, role, and row survived

Start lesson โ†’
๐Ÿ“…Lab 2.6.525 min

Maintenance Scheduling and Runbooks

Write a bloat-alert query, a maintenance script, and schedule both with real OS-level cron โ€” no pg_cron required

Start lesson โ†’
Block 2.7

Application Integration & Concurrency Patterns

Push real-time notifications without polling, coordinate work with advisory locks, build a job queue with no external broker, audit every DDL statement automatically, query external sources as local tables, and move application logic into the database itself.

๐Ÿ“ฃLab 2.7.122 min

LISTEN / NOTIFY: Pub/Sub Messaging

Replace a polling loop with a real push model โ€” and see exactly when a listening client actually notices a message

Start lesson โ†’
๐Ÿ”‘Lab 2.7.222 min

Advisory Locks: Application-Level Mutexes

Turn leader election into three lines of SQL, with no external coordination service at all

Start lesson โ†’
๐Ÿ“ฌLab 2.7.322 min

SKIP LOCKED: Building a Job Queue

Dequeue work atomically with no collisions and no external broker โ€” and see exactly how NOWAIT fails differently

Start lesson โ†’
๐Ÿ“‹Lab 2.7.422 min

Event Triggers & DDL Auditing

Capture every schema change automatically โ€” and discover firsthand that DROP needs a completely different event to see it

Start lesson โ†’
๐ŸŒ‰Lab 2.7.525 min

Foreign Data Wrappers: Querying External Sources

Query a genuinely separate cluster and a plain CSV file as if both were local tables โ€” with real filter pushdown, not just convenience syntax

Start lesson โ†’
โš™๏ธLab 2.7.625 min

Stored Functions & Procedures in PL/pgSQL

Move twelve round-trips into one transactional procedure โ€” and prove a failed order leaves no partial damage behind

Start lesson โ†’
Block 3.1

Understanding the Query Planner

Read EXPLAIN output fluently enough to know exactly why a query is slow โ€” bad row estimates, the wrong join strategy, an unhelpful GUC, or work the planner could parallelize but is not.

๐Ÿ”ฌLab 3.1.125 min

EXPLAIN and EXPLAIN ANALYZE

Read a real query plan node by node โ€” and reproduce "30 seconds on production, 0.1 seconds locally" with nothing but a cold cache

Start lesson โ†’
๐Ÿ“ŠLab 3.1.225 min

Planner Statistics and Bad Estimates

Watch the planner badly misjudge two correlated columns, then fix it with one CREATE STATISTICS object โ€” and measure exactly how much better the estimate gets

Start lesson โ†’
๐Ÿ”€Lab 3.1.325 min

Join Strategies

Force the planner's hand between Nested Loop and Hash Join, and measure exactly what the wrong choice actually costs

Start lesson โ†’
โš™๏ธLab 3.1.425 min

Planner Configuration and Query Rewrites

No extensions can be installed on this server โ€” fix bad plans with the GUCs and query shapes PostgreSQL already ships with

Start lesson โ†’
๐ŸงตLab 3.1.525 min

Parallel Query and JIT

This VM has exactly one CPU. Find out, with real measurements, whether parallel query and JIT compilation still do anything on it.

Start lesson โ†’
Block 3.2

Index Engineering

Indexes are the single highest-leverage performance tool in a relational database. Design them well and most production slowdowns never happen at all.

๐ŸŒณLab 3.2.125 min

B-tree Internals and Multi-Column Indexes

A query filters on (status, created_at). There is already an index on (created_at, status). It is not being used. Prove why, then fix it.

Start lesson โ†’
๐Ÿ”Lab 3.2.225 min

Partial and Expression Indexes

99% of these rows will never be queried by status again. Index only the 1% that matters, and measure exactly how much smaller that makes it.

Start lesson โ†’
๐Ÿ“‡Lab 3.2.325 min

Covering Indexes and Index-Only Scans

An Index Only Scan still touched the table heap once. The index was never the problem โ€” the visibility map was.

Start lesson โ†’
๐Ÿ“šLab 3.2.425 min

GIN for Full-Text Search and JSONB

LIKE '%word%' cannot use a B-tree index no matter how it is built. GIN indexes a completely different structure โ€” and actually can.

Start lesson โ†’
๐Ÿ“‰Lab 3.2.525 min

BRIN, Hash, and Choosing the Right Index Type

500,000 rows in physical time order. A B-tree index on created_at costs 11MB. A BRIN index costs 24kB โ€” for the same query support.

Start lesson โ†’
๐Ÿ”งLab 3.2.625 min

Index Maintenance and Bloat

Two indexes on the same table. One has never been scanned once. The other is real, measured, 33% fragmented. Find both, and fix only the one that matters.

Start lesson โ†’
๐ŸซงLab 3.2.725 min

Bloom Indexes: Multi-Column Equality at Minimal Cost

Five low-selectivity columns, queried in every combination. Five B-tree indexes cost 10MB combined. One bloom index covers all of them at 3.1MB.

Start lesson โ†’
Block 3.3

Advanced SQL Patterns

Solve complex analytical problems inside the database, where the data already lives, instead of shipping rows across the network to solve them in application code.

๐ŸŒฒLab 3.3.125 min

CTEs and Recursive Queries

An org chart traversal loops through 7 levels in application code, one database round trip per level. Replace it with one recursive query.

Start lesson โ†’
๐ŸชŸLab 3.3.225 min

Window Functions

A 7-day moving average, a cumulative total, and a day-over-day change โ€” all three, plus the raw daily number, without collapsing a single row.

Start lesson โ†’
โ†ช๏ธLab 3.3.325 min

LATERAL Joins

"For each customer, their 3 most recent orders." One approach costs less on paper. The other one is actually faster, measured.

Start lesson โ†’
๐Ÿ“„Lab 3.3.425 min

JSONB: Documents in PostgreSQL

100,000 event payloads stored as JSONB. Query inside them, extract nested values, and index them โ€” all without ever normalizing them into columns.

Start lesson โ†’
๐Ÿ“…Lab 3.3.525 min

Arrays and Range Types

A check constraint at the application layer is unreliable. Make double-booking a room structurally impossible at the database level instead.

Start lesson โ†’
๐Ÿ”—Lab 3.3.625 min

Writeable CTEs: Atomic Data Pipelines

SELECT into Python, then INSERT, then DELETE โ€” three round trips, with a real window where data exists in both places or neither. One writeable CTE closes that window completely.

Start lesson โ†’
๐Ÿ“ŠLab 3.3.725 min

Window Frames, crosstab & Advanced Analytics

A rolling average that silently absorbs an extra day across a data gap. A pivot table for the board. An average computed 46x faster from 1% of the data. Three requests, three real tools.

Start lesson โ†’
Block 3.4

Schema Design for Scale

A schema decision made at design time determines whether a database performs the same way at 100 million rows as it did at 100,000. Every lab here is a real pattern that breaks at scale.

๐Ÿ—‚๏ธLab 3.4.125 min

Table Partitioning

A 2-billion-row logs table full-scans on every date-filtered query, despite an index. Partitioning eliminates the irrelevant 99% before a single row is touched.

Start lesson โ†’
๐ŸžLab 3.4.225 min

TOAST and Large Column Storage

A common assumption says an unselected large column still silently costs I/O. Checked directly against the real database, that assumption turns out to be wrong โ€” and the real cost lives somewhere more specific.

Start lesson โ†’
๐Ÿ”ฅLab 3.4.325 min

HOT Updates and fillfactor

A table taking thousands of updates per second is generating enormous WAL volume and index bloat. HOT updates are the structural fix โ€” when they can happen at all.

Start lesson โ†’
๐Ÿ“ธLab 3.4.425 min

Materialized Views and Refresh Strategies

A 90-second aggregation query runs on every page load. A materialized view pre-computes it once โ€” the real challenge is refreshing it without blocking every reader while it happens.

Start lesson โ†’
๐Ÿ’ฝLab 3.4.525 min

Tablespaces and Storage Placement

Index I/O and table I/O are competing on the same disk, saturating the queue. Moving indexes to a second volume immediately separates the two workloads.

Start lesson โ†’
Block 3.5

Server Configuration Tuning

Configuration tuning is guesswork without a mental model of what each parameter actually controls. This block builds that model against this VM's real, measured hardware โ€” not an imagined 64GB server.

๐Ÿง Lab 3.5.125 min

Memory Tuning

Verify shared_buffers with a restart, then compare disk and memory sorts using real query plans.

Start lesson โ†’
โฑ๏ธLab 3.5.225 min

WAL and Checkpoint Tuning

A common reference says checkpoint stats live in pg_stat_bgwriter. Checked directly on this PostgreSQL 18 server, that view no longer has them at all.

Start lesson โ†’
๐ŸงตLab 3.5.325 min

Parallel Query Tuning

The curriculum imagines 16 idle CPU cores. This VM has exactly one, confirmed directly. Tune parallel query anyway โ€” and measure the honest result.

Start lesson โ†’
๐Ÿ”’Lab 3.5.425 min

Connections, Timeouts, and Deadlocks

A connection sits idle inside an open transaction. A query runs forever. Two sessions lock each other out permanently. Three real problems, three real safety timeouts.

Start lesson โ†’
Block 3.6

Diagnostics Under Pressure

Each lab starts with an incident. You are on-call, the SLA is 30 minutes away, and there is no one else to ask. Go.

๐Ÿ“ˆLab 3.6.125 min

pg_stat_statements: Finding the Real Slow Queries

A developer shows you a query that takes 2 seconds. A different query, called 50,000 times a minute, might be costing far more in total. pg_stat_statements reveals which one actually matters.

Start lesson โ†’
๐Ÿ”—Lab 3.6.225 min

Lock Contention Diagnosis

The application is intermittently slow. Several sessions are waiting on locks. Build the real chain, find the one session actually responsible, and terminate only that one.

Start lesson โ†’
๐Ÿ•ต๏ธLab 3.6.325 min

auto_explain and Slow Query Forensics

A slow query only fires under specific production load and cannot be reproduced in testing. auto_explain captures its real execution plan automatically, the moment it actually happens.

Start lesson โ†’
๐ŸŒŠLab 3.6.425 min

PgBouncer Tuning and Connection Storms

Black Friday. A real connection storm arrives. PgBouncer is confirmed absent on this server โ€” find out exactly what PostgreSQL itself does, and does not do, when far too many connections arrive at once.

Start lesson โ†’
๐ŸšจLab 3.6.540 min

Disaster Scenario Labs

Four real incidents, back to back, on the same server. A dropped table, a crashed primary, a bloating replication slot, and a transaction ID wraparound check โ€” each one genuinely reproduced, not simulated.

Start lesson โ†’
Block 3.7

Extensions & Real-World Patterns

Five production requests arrive this sprint. A junior engineer reaches for a separate service each time โ€” every one of them is solvable inside PostgreSQL, with an extension already available on this VM.

๐Ÿ”Lab 3.7.130 min

Fuzzy Search Toolkit: pg_trgm, unaccent & fuzzystrmatch

Customer search is broken three different ways: an accent, a typo, and a phonetic variant. Three genuine extensions fix the three real cases โ€” and they compose into one function.

Start lesson โ†’
๐Ÿ“Lab 3.7.225 min

Geospatial Queries Without PostGIS

The mobile app needs the 5 nearest cafes, a count within a delivery zone, and a point-in-polygon check. PostGIS is confirmed absent on this server โ€” PostgreSQL's own native geometric types genuinely cover all three.

Start lesson โ†’
๐ŸงฎLab 3.7.325 min

Custom Aggregates, Ordered-Set & Hypothetical-Set Aggregates

The finance team needs a geometric mean. The risk team needs a 95th percentile. The sales team wants a hypothetical rank without inserting a row. All three are built-in, or writable, directly in SQL.

Start lesson โ†’
๐Ÿ“ฆLab 3.7.420 min

Table Defragmentation: VACUUM FULL's Real Lock Cost

A table with 18 months of deletes is mostly empty space. pg_repack would reclaim it online โ€” confirmed absent on this server. What VACUUM FULL genuinely costs instead is demonstrated directly.

Start lesson โ†’
๐Ÿ“กLab 3.7.525 min

Logical Decoding & Change Data Capture

A new data warehouse pipeline needs every row change in real time, with no polling and no application code changes. Logical decoding turns the real WAL into a structured change stream.

Start lesson โ†’