DOCODIVE
Advanced Free Learning Path

Databases Advanced: Distributed Systems & Warehousing

Master the databases behind internet-scale systems — distributed architecture, consensus, sharding, CDC, data warehousing, columnar storage, query optimization, and a distributed analytics capstone.

10–14 weeks 40 lessons 1 capstone Databases Intermediate required
Start Learning
01

Distributed Database Architecture

28 min
What you'll learn
  • Understand distributed databases
  • Learn the design trade-offs
  • Know replication vs sharding

A distributed database spreads data across multiple nodes for scale and resilience. Two core strategies: replication (copies of the same data on different nodes — read scale + failover) and sharding (different data on different nodes — write scale). Every distributed system is built from these primitives, combined and traded off. The fundamental tension: you gain scale and availability but pay in complexity and consistency.

distributed.py
# Replication: copies of SAME data
#   node_A: users 1-1000 (primary)
#   node_B: users 1-1000 (replica)
# Sharding: DIFFERENT data
#   shard_0: users 1-500k
#   shard_1: users 500k-1M
Live Preview
Distributed Database Architecture
node_A
node_B
node_C
🔎 Important: Replicate for reads and failover, shard for write scale. Most real systems do both.
Try it yourself

What's the difference between replication and sharding?

Copies vs split.
Replication copies the same data; sharding splits different data across nodes.
02

Consistent Hashing

26 min
What you'll learn
  • Distribute keys across nodes
  • Minimize rehashing on node changes
  • Use virtual nodes

Consistent hashing maps keys to nodes on a ring, so adding/removing a node only remaps a fraction of keys — unlike naive modulo hashing where every key moves. Virtual nodes (many points per physical node) balance the load. This is how distributed caches and databases (Redis Cluster, Cassandra, DynamoDB) distribute data. It's THE algorithm for elastic scaling.

hashing.py
import hashlib

def ring_position(key):
    return int(hashlib.md5(str(key).encode()).hexdigest(), 16)

# Keys map to positions on a ring; each node owns a range
print(ring_position('user:42') % 100)
Live Preview
Consistent Hashing
key
hash
node
✓ Best Practice: Consistent hashing = minimal reshuffling when nodes change. The ring is the key insight.
Try it yourself

Why is naive modulo hashing bad for elastic clusters?

Node changes.
Every key remaps when node count changes, causing mass cache misses.
03

Two-Phase Commit (2PC)

26 min
What you'll learn
  • Understand atomic commits across nodes
  • Learn the prepare/commit phases
  • Know 2PC limitations

Two-Phase Commit atomically commits a transaction across multiple databases. Phase 1 (prepare): coordinator asks all nodes 'can you commit?' — each locks and votes. Phase 2 (commit/abort): all commit or all abort. It guarantees atomicity across nodes, but blocks during failures and is slow — the classic reason distributed systems prefer eventual consistency for most operations.

2pc.py
# Phase 1: COORDINATOR -> 'PREPARE?' -> NODE A, NODE B
# Phase 2: all 'YES' -> 'COMMIT' ; any 'NO' -> 'ABORT'
# Blocks if a node is unreachable (coordinator waits)
Live Preview
Two-Phase Commit (2PC)
PREPARE
COMMIT
⚠️ Common Mistake: 2PC gives atomicity but blocks on failure — use only where cross-node atomicity is truly required.
Try it yourself

What are the two phases of 2PC?

Prepare + commit.
Prepare (vote) and Commit/Abort.
04

Paxos & Raft Consensus

30 min
What you'll learn
  • Understand consensus
  • Learn leader election
  • Replicate a log reliably

Consensus algorithms let a cluster agree on a value even with node failures. Raft (more understandable than Paxos) elects a leader, replicates a log of commands to followers, and commits when a majority agree. This is how etcd, Consul, and modern distributed databases maintain consistency. Consensus is the foundation of reliable distributed systems — the 'brain' of the cluster.

consensus.py
# Raft: leader election -> log replication -> commit on majority
# Leader receives write, replicates to followers
# Commit when majority (quorum) acknowledge
# If leader fails -> new election
Live Preview
Paxos & Raft Consensus
leader
follower
follower
🔎 Important: Consensus = majority agreement. It's how distributed systems stay consistent when nodes fail.
Try it yourself

What's a 'quorum' in Raft?

Majority.
A majority of nodes (>50%) agreeing on a value.
05

Eventual Consistency Patterns

24 min
What you'll learn
  • Design for eventual consistency
  • Understand staleness windows
  • Handle conflict resolution

Eventual consistency means replicas converge over time — a read may briefly return stale data after a write. It enables massive scale (no coordination latency) at the cost of temporary inconsistency. Patterns: read-your-writes (user sees own writes), monotonic reads (never see time go backward), and conflict resolution (last-write-wins vs merge). Most internet-scale systems are eventually consistent.

eventual.py
# Write to primary, async replication to replicas
# Replica lag = staleness window (usually < 1s)
# Read-your-writes: route user's reads to primary after their writes
Live Preview
Eventual Consistency Patterns
write
async replicate
converge
🔎 Important: Eventual consistency isn't a bug — it's the deliberate trade that makes internet scale possible.
Try it yourself

What's the main benefit of eventual consistency?

Scale.
No coordination overhead — massively higher write throughput and availability.
06

CRDTs (Conflict-Free Replicated Data Types)

28 min
What you'll learn
  • Merge data without conflicts
  • Use counters and sets
  • Build offline-first apps

CRDTs are data structures that merge deterministically regardless of update order — two nodes can update independently and always converge. A grow-only counter, an add-wins set. They power collaborative editing (Google Docs-style), offline-first apps, and multi-region sync. The magic: the merge operation is commutative and associative, so order doesn't matter.

crdt.py
# Grow-only counter: only increments, never conflicts
# Node A: count = 3 (saw +1, +2)
# Node B: count = 5 (saw +1, +2, +3, -2 ignored)
# Merge: max(A, B) = 5 — converged
Live Preview
CRDTs (Conflict-Free Replicated Data Types)
Node A: 3
Node B: 5
merge
5
✓ Best Practice: CRDTs eliminate conflicts by making the merge operation itself order-independent — no locks, no coordination.
Try it yourself

Why do CRDTs avoid conflicts?

Commutative merge.
Their merge is commutative/associative — order doesn't matter, so no conflict.
07

Vector Clocks

24 min
What you'll learn
  • Track causal ordering
  • Detect concurrent updates
  • Understand causality in distributed systems

A vector clock tracks, for each node, how many events it has seen — enabling detection of causal relationships between events. Two events are concurrent if their vector clocks are incomparable (neither dominates). This is how systems detect conflicts and enforce causal consistency. Vector clocks trade size (one entry per node) for precise causality tracking.

vector.py
# Node A clock: {A: 3, B: 1}
# Node B clock: {A: 1, B: 4}
# Incomparable => concurrent writes => conflict
Live Preview
Vector Clocks
{A:3, B:1}
{A:1, B:4}
=
concurrent
💡 Tip: Vector clocks answer 'did one event happen before another?' — the foundation of causality in distributed systems.
Try it yourself

What do incomparable vector clocks mean?

Neither before.
The events are concurrent — no causal ordering.
08

Saga Pattern (Distributed Transactions)

28 min
What you'll learn
  • Manage transactions across services
  • Use compensating actions
  • Design for partial failure

The Saga pattern manages a distributed transaction as a sequence of local transactions, each with a compensating action (undo). If a step fails, previously-completed steps are rolled back via their compensations. Unlike 2PC, sagas don't block — they're eventually consistent. This is how microservices handle multi-step operations like 'place order + charge card + ship item'.

saga.py
# Saga steps:
# 1. Reserve inventory  -> compensate: release inventory
# 2. Charge payment     -> compensate: refund payment
# 3. Ship order         -> compensate: cancel shipment
# If step 3 fails, run compensations for 2 then 1
Live Preview
Saga Pattern (Distributed Transactions)
step 1
step 2
fail
compensate
🔎 Important: Sagas trade atomicity (2PC) for availability — each step is a local transaction with an undo.
Try it yourself

What's a compensating action?

Undo.
An operation that undoes a previously-completed saga step.
09

Change Data Capture (CDC)

26 min
What you'll learn
  • Stream database changes
  • Use Debezium
  • Keep systems in sync

Change Data Capture captures row-level changes (inserts/updates/deletes) from the database's transaction log and streams them to other systems — data warehouses, caches, search indexes. Debezium (on top of Kafka) is the standard tool. CDC keeps systems in sync in near-real-time without batch ETL, and without touching the source app. It's the backbone of event-driven data pipelines.

cdc.py
# CDC: read WAL (write-ahead log)
# INSERT users -> {user_id: 1, name: 'Ali'}
# Stream to: search index, cache, warehouse
Live Preview
Change Data Capture (CDC)
WAL
Debezium
Kafka
✓ Best Practice: CDC reads the transaction log — no app changes, no polling, near-real-time sync to everywhere.
Try it yourself

What does CDC read to detect changes?

Log.
The database's transaction log (WAL).
10

Materialized Views

22 min
What you'll learn
  • Precompute query results
  • Use for expensive aggregations
  • Understand refresh strategies

A materialized view stores the RESULT of a query physically — so expensive aggregations run once, not every read. Dashboards over millions of rows become instant. The trade-off: results get stale between refreshes. Refresh strategies: on-demand, scheduled, or (in some DBs) incremental. Materialized views are the bridge between raw data and fast analytics.

matview.sql
CREATE MATERIALIZED VIEW daily_sales AS
SELECT date_trunc('day', order_date) AS day, SUM(total) AS revenue
FROM orders
GROUP BY day;

REFRESH MATERIALIZED VIEW daily_sales;
Live Preview
Materialized Views
raw query
precomputed
💡 Tip: Materialized views trade freshness for speed — refresh them on a schedule that matches your staleness tolerance.
Try it yourself

Why use a materialized view?

Slow queries.
To precompute expensive aggregations so queries are instant.
11

Data Warehouse Fundamentals

26 min
What you'll learn
  • Understand data warehouses
  • Distinguish OLAP from OLTP
  • Design for analytics

A data warehouse is a dedicated analytical database optimized for complex queries over historical data — separate from the operational (OLTP) database so analytics doesn't slow down the app. It stores denormalized, subject-oriented, time-variant data. The separation is key: OLTP optimizes fast writes; the warehouse optimizes fast reads over millions of rows. This is the foundation of business intelligence.

warehouse.py
# OLTP: normalized, fast writes, current data
# Warehouse: denormalized, fast reads, historical data
# ETL moves data from OLTP -> warehouse
Live Preview
Data Warehouse Fundamentals
OLTP
ETL→
Warehouse
BI
🔎 Important: Never run analytics on your transactional DB — the warehouse exists to keep them separate.
Try it yourself

Why separate warehouse from operational DB?

Contention.
Analytical queries would compete with transactional writes, slowing the app.
12

Star & Snowflake Schemas

26 min
What you'll learn
  • Design analytical schemas
  • Use fact and dimension tables
  • Know star vs snowflake

Analytical schemas organize data into fact tables (measurements: sales, events) and dimension tables (descriptors: customer, product, date). The star schema keeps dimensions denormalized (flat, fast); the snowflake schema normalizes dimensions (nested, less redundancy but more joins). Star is the default for query speed; snowflake saves space. This is the classic dimensional modeling pattern.

star.sql
# STAR: fact_sales <-> dim_customer, dim_product, dim_date
# SNOWFLAKE: dim_customer -> dim_city -> dim_country (normalized)
Live Preview
Star & Snowflake Schemas
fact_sales
dim_customerdim_productdim_date
✓ Best Practice: Star schema = fewer joins = faster queries. Snowflake = less redundancy = slower queries. Pick star by default.
Try it yourself

What's a fact table?

Measurements.
A table of quantitative measures/events (e.g., sales transactions).
13

ETL vs ELT

22 min
What you'll learn
  • Compare ETL and ELT
  • Understand modern pipelines
  • Choose the right pattern

ETL (Extract, Transform, Load) transforms data BEFORE loading into the warehouse — traditional, good for strict governance. ELT (Extract, Load, Transform) loads raw data first, transforms inside the warehouse — modern, leverages warehouse compute power and flexibility. Cloud warehouses (Snowflake, BigQuery) made ELT dominant. The key shift: transformation happens in the warehouse, not a separate tool.

etl.py
# ETL: extract -> transform (in ETL tool) -> load clean
# ELT: extract -> load raw (into warehouse) -> transform (SQL in warehouse)
Live Preview
ETL vs ELT
E
T
L
💡 Tip: Modern cloud stacks default to ELT — raw data first, SQL transforms in the warehouse, maximum flexibility.
Try it yourself

Why did ELT become dominant?

Cloud warehouses.
Cloud warehouses are powerful enough to transform data in-place, making pre-load transformation unnecessary.
14

OLTP vs OLAP Systems

22 min
What you'll learn
  • Distinguish transactional and analytical
  • Understand optimization differences
  • Choose the right system

OLTP (transactional) optimizes for many small, fast writes — bank transactions, shopping carts. OLAP (analytical) optimizes for few large, complex reads — reports, dashboards. The optimizations conflict: row stores for OLTP, column stores for OLAP. Using the wrong system for a workload causes massive performance problems. This distinction drives almost every database architecture decision.

oltp.py
# OLTP: row store, many small writes
#   UPDATE account SET balance = ... WHERE id = 123
# OLAP: column store, few large reads
#   SELECT SUM(revenue) FROM sales WHERE year = 2026
Live Preview
OLTP vs OLAP Systems
OLTP: writes
OLAP: reads
🔎 Important: OLTP = many small writes. OLAP = few large reads. Never mix them on one system at scale.
Try it yourself

A bank transaction is OLTP or OLAP?

Small write.
OLTP — many small, fast writes.
15

Columnar Storage

26 min
What you'll learn
  • Understand column-oriented storage
  • Know why analytics benefit
  • Learn compression advantages

Columnar storage stores each column's data together (instead of each row). For analytical queries touching few columns over millions of rows, this is transformative: scan only needed columns, compress similar values (same column = same type = great compression), and vectorize operations. Columnar DBs (ClickHouse, BigQuery, Redshift) are orders of magnitude faster for aggregations than row stores.

columnar.py
# Row store: [id, name, age], [1, 'Ali', 25], [2, 'Sara', 30]
# Column store: id[1,2], name['Ali','Sara'], age[25,30]
# Query 'AVG(age)' reads ONLY the age column
Live Preview
Columnar Storage
rows
columns
=
fast analytics
✓ Best Practice: Columnar = only read the columns you need + superior compression. It's why analytics warehouses are fast.
Try it yourself

Why does columnar storage compress better?

Same type.
Same column = same data type = similar values compress extremely well.
16

Query Optimizer Internals

28 min
What you'll learn
  • Understand how queries get optimized
  • Learn cost-based optimization
  • Know join algorithm choices

The query optimizer transforms your SQL into an efficient execution plan. It estimates costs for different strategies (which index, which join order, which join algorithm — nested loop, hash join, merge join) and picks the cheapest. Understanding the optimizer's choices explains why some queries are fast and others slow. It's the 'compiler' of the database.

optimizer.sql
# Optimizer choices:
# 1. Which index to use (or full scan)
# 2. Join order (A⋈B vs B⋈A)
# 3. Join algorithm (nested loop / hash / merge)
# Picks lowest estimated cost
Live Preview
Query Optimizer Internals
SQL
optimizer
plan
🔎 Important: SQL says WHAT, the optimizer figures out HOW. Understanding its choices is the key to query tuning.
Try it yourself

What does the optimizer minimize?

Estimated.
Estimated execution cost (I/O + CPU).
17

Advanced EXPLAIN & Profiling

26 min
What you'll learn
  • Read complex EXPLAIN output
  • Identify actual vs estimated rows
  • Profile query execution

EXPLAIN ANALYZE shows both estimated and ACTUAL rows/time — the discrepancy between them reveals stale statistics. Profiling breaks down where time goes (scan, join, sort). The workflow: run EXPLAIN ANALYZE, look for row-count mismatches (planner guessed wrong), expensive nodes (sorts, hash joins), and fix accordingly. This turns slow-query debugging from guessing into a precise process.

explain.sql
EXPLAIN ANALYZE
SELECT o.id, c.name
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.total > 1000;
Live Preview
Advanced EXPLAIN & Profiling
Hash Join (actual=120, est=5000)
⚠ row mismatch
✓ Best Practice: The gap between estimated and actual rows is your #1 clue — big gap = stale statistics = bad plan.
Try it yourself

What does a big estimated-vs-actual row gap signal?

Stats.
Stale table statistics — the optimizer made a bad plan.
18

Cost-Based Optimization

24 min
What you'll learn
  • Understand cost models
  • Use statistics (histograms)
  • Improve planner decisions

Cost-based optimization estimates each plan's I/O and CPU cost using table statistics — row counts, distinct values, histograms of value distribution. Accurate statistics = good plans; stale statistics = the planner picks wrong. The fix: keep ANALYZE/VACUUM up to date. This is why 'the database got slow' after bulk data loads — statistics are stale.

cbo.sql
ANALYZE orders;  -- refresh statistics
SELECT * FROM pg_stats WHERE tablename = 'orders';
Live Preview
Cost-Based Optimization
stats
cost model
best plan
💡 Tip: Run ANALYZE after bulk loads — stale statistics are the silent cause of sudden query slowdowns.
Try it yourself

What do stale statistics cause?

Bad plans.
The optimizer picks suboptimal execution plans based on wrong row estimates.
19

Index Scan, Bitmap Scan, Sequential Scan

26 min
What you'll learn
  • Know the three scan types
  • Understand when each is optimal
  • Read plans to spot wrong scans

Three ways to read data: Sequential Scan (full table, best for large fraction of rows), Index Scan (random access via index, best for few rows), Bitmap Index Scan (combines multiple indexes, best for medium selectivity). The optimizer picks based on row estimates and row order correlation. Spotting the wrong scan in EXPLAIN is the core query-tuning skill.

scans.sql
EXPLAIN SELECT * FROM users WHERE age > 30 AND city = 'Lahore';
-- Bitmap Heap Scan on users
--   Bitmap Index Scan (age + city indexes combined)
Live Preview
Index Scan, Bitmap Scan, Sequential Scan
Seq
Index
Bitmap
🔎 Important: Sequential = full table (large results). Index = few rows. Bitmap = combining indexes. Learn to spot which is optimal.
Try it yourself

When is a sequential scan actually BETTER than an index scan?

Most rows.
When returning most of the table — random index access is then slower than reading sequentially.
20

Sharding Strategies

26 min
What you'll learn
  • Choose shard keys
  • Understand range vs hash sharding
  • Avoid hot spots

Sharding splits data across nodes by a shard key. Range sharding (by date, id ranges) is intuitive but risks hot spots (recent data on one node). Hash sharding (hash(key) mod N) balances uniformly but makes range queries expensive. The shard key choice is the hardest decision in sharding — it determines access patterns forever. Choose based on your dominant query pattern.

sharding.py
# Range: shard by user_id 0-1M, 1M-2M (hot spots possible)
# Hash: shard = hash(user_id) % 4 (uniform, no range queries)
# Consider: hot user sharding (isolate heavy users)
Live Preview
Sharding Strategies
shard_0
shard_1
shard_2
⚠️ Common Mistake: Shard key is a one-way door — changing it requires re-sharding ALL data. Choose very carefully.
Try it yourself

What's a shard 'hot spot'?

One node.
Most traffic concentrating on a single shard, causing imbalance.
21

Read/Write Splitting

22 min
What you'll learn
  • Route reads and writes separately
  • Scale read-heavy workloads
  • Handle replication lag

Read/write splitting routes writes to the primary and reads to replicas — scaling read-heavy apps (most web apps are read-dominant). The challenge: replication lag means replicas may briefly return stale data. Solutions: route critical reads to primary, use read-your-writes consistency, and monitor lag. This is the standard scaling pattern for PostgreSQL/MySQL.

rwsplit.py
# writes -> primary
# reads -> replica (if staleness tolerable)
# critical reads (after write) -> primary
Live Preview
Read/Write Splitting
writes → primary
reads → replicas
✓ Best Practice: Most apps are read-heavy — splitting reads to replicas is the highest-leverage scaling move.
Try it yourself

What's the main risk of read replicas?

Stale.
Replication lag — reads may briefly return stale data.
22

Multi-Region Replication

26 min
What you'll learn
  • Replicate across regions
  • Reduce latency for global users
  • Handle cross-region consistency

Multi-region replication places data near users worldwide, cutting latency dramatically. The trade-off: cross-region writes pay network latency, and consistency becomes eventual (regions can't stay strongly consistent across oceans). Strategies: single-primary multi-region (writes to one region), multi-primary (writes anywhere, conflict resolution), and read-only replicas per region. This is global-scale database design.

multiregion.py
# Region US: primary
# Region EU: read replica (latency for EU users ~10ms)
# Region APAC: read replica
# Cross-region writes: async replication (eventual)
Live Preview
Multi-Region Replication
US
EU
APAC
🔎 Important: Multi-region = lower latency but eventual consistency across regions. Physics (speed of light) forces this.
Try it yourself

Why can't multi-region be strongly consistent?

Latency.
Cross-region network latency (speed of light) makes synchronous replication too slow.
23

Disaster Recovery & PITR

24 min
What you'll learn
  • Recover from disasters
  • Use point-in-time recovery
  • Meet RPO/RTO targets

Point-In-Time Recovery (PITR) restores a database to any moment using backups + transaction logs (WAL). Two metrics define recovery quality: RPO (Recovery Point Objective — how much data you can lose, in time) and RTO (Recovery Time Objective — how fast you recover). Continuous WAL archiving gives near-zero RPO. This is the difference between 'we lost data' and 'we restored to 30 seconds ago'.

pitr.py
# Full backup + continuous WAL archiving
# Restore: load last full backup, replay WAL to desired point
# RPO: seconds (WAL shipped continuously)
# RTO: minutes-hours
Live Preview
Disaster Recovery & PITR
backup
+
WAL
=
PITR
⚠️ Common Mistake: Test restores regularly — untested backups are wishes, not backups. Know your RPO/RTO.
Try it yourself

What does RPO measure?

Data loss.
Maximum acceptable data loss, measured in time (e.g., 5 minutes).
24

Connection Management at Scale

22 min
What you'll learn
  • Manage thousands of connections
  • Use multiplexing
  • Avoid connection exhaustion

Databases have connection limits (often 100s). Apps serving thousands of users need connection pooling and multiplexing: PgBouncer pools connections, multiplexing many clients over few DB connections. Without it, 'too many connections' crashes apps under load. This is non-negotiable production infrastructure for any serious web app.

pooling.py
# PgBouncer: 10k app clients -> 200 DB connections
# Transaction pooling: connection released after each transaction
# Session pooling: held for the session (needed for some features)
Live Preview
Connection Management at Scale
10k clients
200 conns
✓ Best Practice: Connection multiplexing is non-negotiable at scale — the DB connection limit is fixed, your users are not.
Try it yourself

Why not just open unlimited DB connections?

Resource.
Each connection costs memory/CPU; DBs have hard limits and degrade beyond them.
25

Caching Layers (Redis + Memcached)

24 min
What you'll learn
  • Layer caching strategically
  • Use Redis vs Memcached
  • Prevent cache stampedes

A caching layer (Redis/Memcached) absorbs repeated reads so the database only handles writes and cache misses. Redis is richer (data structures, persistence, pub/sub); Memcached is simpler (pure cache, multi-threaded). Cache stampede prevention (when many clients miss simultaneously and hammer the DB) uses locking or TTL jitter. Caching is the cheapest, highest-impact performance win.

caching.py
# Cache: key -> value in Redis
# get -> hit? return : query DB, set cache, return
# Stampede fix: lock on miss, or randomized TTL
Live Preview
Caching Layers (Redis + Memcached)
Redis
hit
fast
✓ Best Practice: Cache the top 1% of hot queries and you handle 90% of read load. The cheapest performance win there is.
Try it yourself

What's a cache stampede?

Simultaneous miss.
Many clients miss the cache at once and overload the database.
26

Data Encryption at Rest & Transit

22 min
What you'll learn
  • Encrypt stored and moving data
  • Use TLS and TDE
  • Meet security compliance

Encryption at rest protects data on disk (full-disk encryption, Transparent Data Encryption); encryption in transit protects data moving over the network (TLS/SSL). Both are required for security compliance (PCI, HIPAA, GDPR). Key management (where keys live, who can access) is the hard part. This is baseline database security for any sensitive data.

encryption.py
# At rest: TDE (transparent data encryption) encrypts data files
# In transit: SSL/TLS encrypts client-database connections
# Key management: keys in KMS, rotated regularly
Live Preview
Data Encryption at Rest & Transit
at rest 🔒
in transit 🔒
🔎 Important: Encryption is table stakes for sensitive data — compliance depends on it. The keys are the crown jewels.
Try it yourself

At rest vs in transit encryption?

Disk vs network.
At rest = stored data; in transit = data moving over the network.
27

Auditing & Compliance (GDPR)

24 min
What you'll learn
  • Track data access and changes
  • Meet GDPR requirements
  • Implement audit logs

Auditing tracks WHO did WHAT to data and WHEN — essential for compliance (GDPR, HIPAA, SOC 2) and security forensics. Database audit logs, trigger-based audit tables, and dedicated audit tools (pgAudit) capture this. GDPR adds requirements: right to access, right to erasure ('delete my data'), data minimization. Auditing is how you prove compliance.

audit.sql
CREATE EXTENSION pgaudit;
SET pgaudit.log = 'write, ddl';
-- Now every write and DDL is logged with user + timestamp
Live Preview
Auditing & Compliance (GDPR)
who
+
what
+
when
⚠️ Common Mistake: If you can't prove who changed data, you can't pass a compliance audit. Log everything sensitive.
Try it yourself

What does GDPR's 'right to erasure' mean?

Delete.
Users can request complete deletion of their personal data.
28

Backup Strategies Deep Dive

24 min
What you'll learn
  • Design backup strategies
  • Use full/incremental/differential
  • Verify restores

Backup strategy: full backups (everything, periodic), incremental (changes since last backup, frequent), differential (changes since last FULL backup). The 3-2-1 rule: 3 copies, 2 media types, 1 offsite. Critical practice: regularly TEST restores — a backup you can't restore is worthless. RPO/RTO drive the strategy choice. This is operational database maturity.

backup.sql
# Full: weekly, complete snapshot
# Incremental: daily, changes since last backup
# 3-2-1: 3 copies, 2 media, 1 offsite
# TEST restore monthly
Live Preview
Backup Strategies Deep Dive
full
+
incremental
+
3-2-1
🔎 Important: Backups are worthless until you've tested the restore. Make restore testing a regular ritual.
Try it yourself

What's the 3-2-1 backup rule?

Copies/media/offsite.
3 copies, 2 different media types, 1 offsite copy.
29

Performance Schema & Metrics

24 min
What you'll learn
  • Collect performance data
  • Identify bottlenecks
  • Set up monitoring dashboards

Performance monitoring uses built-in instrumentation (PostgreSQL's pg_stat_* views, MySQL's performance_schema) to track: query latency, lock waits, cache hit ratio, connection usage, and I/O. Prometheus + Grafana turn these into dashboards with alerts. Key insight: you can't fix what you don't measure. Monitoring turns 'users say it's slow' into precise data.

metrics.sql
SELECT * FROM pg_stat_activity;  -- current queries
SELECT * FROM pg_stat_database;  -- cache hits, commits
SELECT * FROM pg_locks;          -- lock contention
Live Preview
Performance Schema & Metrics
99%
cache hit
0.2s
avg query
✓ Best Practice: Measure first, optimize second. Monitoring is the foundation of every performance investigation.
Try it yourself

Why monitor cache hit ratio?

Memory.
Low hit ratio means insufficient memory — data being read from disk instead of cache.
30

Slow Query Analysis Workflow

26 min
What you'll learn
  • Systematically fix slow queries
  • Use logs + EXPLAIN
  • Iterate on optimization

The slow-query workflow: (1) identify slow queries (log_min_duration_statement, pg_stat_statements), (2) run EXPLAIN ANALYZE, (3) find the bottleneck (seq scan? bad join? sort?), (4) fix (add index, rewrite query, update stats), (5) verify improvement. This disciplined loop beats guessing — each step is evidence-driven. It's the difference between 'I tried stuff' and 'I fixed it'.

slowquery.sql
# 1. Find slow queries
SELECT query, mean_exec_time FROM pg_stat_statements
ORDER BY mean_exec_time DESC LIMIT 10;
# 2. EXPLAIN ANALYZE the slowest
# 3. Fix (index, rewrite)
# 4. Verify improvement
Live Preview
Slow Query Analysis Workflow
find
analyze
fix
✓ Best Practice: Slow query fixes are a process, not a guess. Follow the loop every time.
Try it yourself

First step when a query is slow?

Evidence.
Run EXPLAIN ANALYZE to see the actual execution plan.
31

Advanced Table Partitioning

24 min
What you'll learn
  • Partition by range/list/hash
  • Use partition pruning
  • Manage huge tables

Advanced partitioning: RANGE (time-based), LIST (category-based), HASH (uniform distribution). Partition pruning means queries touching one partition only scan that one — massive speedup. Management benefits: drop old partitions instantly (vs slow deletes), archive easily. For billion-row tables, partitioning is mandatory. Choose the partition key that matches your query filter patterns.

partition.sql
CREATE TABLE events (...) PARTITION BY RANGE (event_date);
CREATE TABLE events_2026_01 PARTITION OF events
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
-- Drop Jan data = DROP TABLE events_2026_01 (instant)
Live Preview
Advanced Table Partitioning
Jan
Feb
Mar
🔎 Important: Partition key should match your WHERE clause — then the optimizer prunes everything else away.
Try it yourself

What's partition pruning?

Skip.
The optimizer only scans partitions relevant to the query, skipping the rest.
32

Full-Text vs Vector Search

26 min
What you'll learn
  • Compare keyword and semantic search
  • Use embeddings for meaning
  • Build hybrid search

Full-text search matches KEYWORDS (exact/stemmed terms). Vector search matches MEANING (embeddings — similar sentences have close vectors). Keyword is precise (great for exact terms); vector finds related content even with different words ('car' ≈ 'automobile'). Modern search systems use HYBRID — keyword + vector — for both precision and semantic recall. Vector databases (pgvector, Pinecone, Weaviate) power RAG and semantic search.

vector.sql
CREATE EXTENSION vector;
CREATE TABLE articles (id INT, content TEXT, embedding vector(384));
-- Semantic query
SELECT id FROM articles
ORDER BY embedding <-> query_embedding LIMIT 10;
Live Preview
Full-Text vs Vector Search
keyword
+
vector
=
hybrid
💡 Tip: Keyword finds 'car', vector finds 'automobile' too. Hybrid search combines both for best results.
Try it yourself

Vector search matches on what?

Meaning.
Semantic meaning via embedding similarity.
33

Graph Databases (Neo4j)

26 min
What you'll learn
  • Model data as graphs
  • Query with Cypher
  • Solve relationship problems

Graph databases store data as nodes and relationships — perfect for highly-connected data: social networks, fraud detection, recommendation engines. Cypher (Neo4j's query language) expresses relationship queries elegantly ('friends of friends') that would be painful recursive SQL. Graph DBs excel at traversal depth, pattern matching, and relationship-centric queries where relational DBs struggle.

cypher.cypher
// Cypher: friends of friends
MATCH (u:User {name: 'Ali'})-[:FRIENDS]->(f)-[:FRIENDS]->(fof)
WHERE fof <> u
RETURN fof.name;
Live Preview
Graph Databases (Neo4j)
(Ali)-[:FRIENDS]->
(Sara)
💡 Tip: Graph DBs win on relationship traversal — if 'friends of friends' is your query pattern, use a graph DB.
Try it yourself

Graph DBs optimize what kind of queries?

Relationships.
Relationship traversal and pattern matching across connected data.
34

Time-Series Databases Deep Dive

24 min
What you'll learn
  • Optimize for timestamped data
  • Use retention policies
  • Downsample and aggregate

Time-series DBs (TimescaleDB, InfluxDB) specialize in timestamp-ordered data: sensor readings, metrics, financial ticks. Key features: hypertables (auto-partition by time), continuous aggregates (precomputed rollups), compression (columnar, huge savings), retention policies (auto-delete old data). Write-heavy, time-range-query workloads are their sweet spot — relational DBs degrade on these.

timeseries.sql
SELECT create_hypertable('metrics', 'time');

-- Continuous aggregate (precomputed hourly rollup)
CREATE MATERIALIZED VIEW hourly_avg
WITH (timescaledb.continuous) AS
SELECT time_bucket('1 hour', time) AS hour, AVG(value)
FROM metrics GROUP BY hour;
Live Preview
Time-Series Databases Deep Dive
time data
hypertable
✓ Best Practice: Continuous aggregates precompute rollups so dashboards query summaries, not raw millions of points.
Try it yourself

What's a retention policy in a TSDB?

Delete old.
Automatic deletion of data older than a threshold.
35

Data Lakes & Lakehouses

28 min
What you'll learn
  • Understand data lakes
  • Learn the lakehouse pattern
  • Separate storage from compute

A data lake stores raw data in cheap object storage (S3) in open formats (Parquet, Iceberg) — any format, any size. A lakehouse adds warehouse features (ACID transactions, schema, SQL) on top of the lake — the best of both: cheap storage + warehouse performance. Iceberg/Delta Lake table formats enable this. The lakehouse is the modern data architecture, replacing rigid warehouses.

lakehouse.sql
# Data lake: raw Parquet files in S3 (any data, cheap)
# Lakehouse: Iceberg table format (ACID, schema, time-travel)
#   SELECT * FROM iceberg_table WHERE ... (SQL on the lake)
Live Preview
Data Lakes & Lakehouses
lake
+
warehouse
=
lakehouse
🔎 Important: Lakehouse = warehouse features on lake economics. Iceberg/Delta are the formats enabling it.
Try it yourself

Lakehouse vs warehouse — main advantage?

Cost.
Cheap object storage with warehouse-grade querying and ACID.
36

Data Governance

26 min
What you'll learn
  • Manage data as an asset
  • Enforce quality and lineage
  • Meet regulatory requirements

Data governance is the discipline of managing data quality, security, lineage, and cataloging across an organization. Components: data catalogs (what data exists), data lineage (where it came from), data quality rules, access policies. It's the framework that makes data trustworthy and compliant. Without governance, data becomes an unmanaged liability; with it, a reliable asset.

governance.py
# Governance pillars:
# Catalog: what data exists (Atlas, Unity Catalog)
# Lineage: where data came from (dbt lineage, OpenLineage)
# Quality: validation rules (Great Expectations)
# Access: who can see what (RBAC/ABAC)
Live Preview
Data Governance
catalog
lineage
quality
✓ Best Practice: Data governance turns 'some data somewhere' into 'trusted, findable, compliant data'.
Try it yourself

What is data lineage?

Origin.
Tracking where data came from and how it's transformed.
37

Distributed Query Engines (Presto/Trino)

26 min
What you'll learn
  • Query across multiple data sources
  • Use Presto/Trino
  • Federate queries

Trino (formerly Presto) is a distributed query engine that runs SQL across MULTIPLE data sources at once — PostgreSQL, S3, Kafka, MySQL — without moving the data. It federates queries, splitting work across worker nodes and pushing filters down to sources. This enables 'one SQL query across your whole data estate'. It's the query layer on top of a data lake/lakehouse.

trino.sql
-- Trino: query Postgres AND S3 in one query
SELECT u.name, o.total
FROM postgres.users u
JOIN s3.orders o ON u.id = o.user_id;
Live Preview
Distributed Query Engines (Presto/Trino)
Postgres
S3
=
one query
💡 Tip: Trino = one SQL interface over everything. No ETL needed for exploratory cross-source queries.
Try it yourself

What does 'federated query' mean?

Multiple sources.
Querying multiple data sources in a single SQL query.
38

OLAP Cube & Rollup Operations

24 min
What you'll learn
  • Understand OLAP cubes
  • Use GROUP BY CUBE/ROLLUP
  • Precompute multi-dimensional aggregates

OLAP cubes precompute aggregates across multiple dimensions (product, region, time) so any slice-and-dice query is instant. SQL's GROUP BY ROLLUP (hierarchical subtotals) and CUBE (all combinations) generate these. The trade-off: precomputation takes storage and compute, but query latency drops to milliseconds. This is the engine behind pivot tables and BI dashboards.

cube.sql
SELECT region, product, SUM(sales) AS total
FROM sales
GROUP BY ROLLUP(region, product);
-- gives: per region+product, per region, grand total
Live Preview
OLAP Cube & Rollup Operations
region
×
product
=
cube
💡 Tip: ROLLUP = hierarchical subtotals, CUBE = all combinations. The SQL behind every BI dashboard.
Try it yourself

ROLLUP vs CUBE — difference?

Combinations.
ROLLUP gives hierarchical subtotals; CUBE gives all dimension combinations.
39

Database-as-a-Service & Serverless

22 min
What you'll learn
  • Use managed databases
  • Understand serverless pricing
  • Offload operational burden

Database-as-a-Service (RDS, Aurora, Cloud SQL) handles backups, patching, replication, failover — you focus on schema and queries. Serverless databases (Aurora Serverless, Neon) scale compute automatically, billing per usage — ideal for variable workloads. The trade-off: less control, vendor lock-in. For most teams, managed DBs are a massive operational win: reliability without the ops team.

dbaas.py
# Managed: backups, replication, failover handled
# Serverless: scales to zero when idle, bursts under load
# You: schema + queries + application logic
Live Preview
Database-as-a-Service & Serverless
☁️ managed
✓ Best Practice: Managed DBs are the default choice for most teams — reliability without a DBA team.
Try it yourself

Main benefit of serverless databases?

Scale.
Automatic scaling and pay-per-use — no idle capacity costs.
40

Capstone: Distributed Analytics Platform

70 min
What you'll learn
  • Architect a full data platform
  • Apply warehousing + streaming + caching
  • Document design decisions

Your capstone: architect a complete data platform. Design a data warehouse (star schema) fed by CDC streaming, a caching layer for hot queries, materialized views for dashboards, and a sharding/replication plan for scale. Document RPO/RTO, consistency choices, and security. This integrates everything — the deliverable is a production-grade architecture, portfolio-ready.

capstone.sql
# Architecture:
# OLTP (Postgres) --CDC--> Kafka --ETL--> Warehouse (star schema)
# Warehouse -> materialized views -> dashboards
# Redis cache for hot queries
# Replication for read scale, sharding for write scale
Live Preview
Capstone: Distributed Analytics Platform
OLTP → CDC → Warehouse
+ Redis cache + sharding
✓ Best Practice: This capstone = warehouse + streaming + caching + scaling — the complete modern data platform.
Try it yourself

Name the core components of a modern data platform.

Pipeline.
OLTP source, CDC/streaming, warehouse/lakehouse, caching, BI/dashboards.
You've completed all 40 advanced lessons. You're now a database architect.

Practice your skills or return to the Databases hub.

📱 Scan this QR code with your phone camera to instantly open this page.

Works on iOS, Android, and any modern device. No app installation required.

Account Verified!

Your email has been verified successfully.