Groundwork

Foundations

Data & storage: where every real app actually lives.

Strip any serious application down and you find the same thing: data, and rules about who can change it. The code around it comes and goes; the data model outlives everything. This page gives you the two big storage families, hands-on practice with tools already on your machine, and the reason this matters more — not less — now that agents write most of the queries.

Why this is AI-native

Agents are excellent at writing SQL and data code — and they will write it confidently whether it's right or wrong. The human's job is judging it: does this query answer the actual question? Will this UPDATE touch three rows or three million? Is this the right shape for the data at all? You can't verify what you can't read. Data fluency is verification fluency.

#The two big families

Nearly every storage system you'll meet is one of two shapes — and most real systems use both, for different jobs.

Relational (SQL)Data lives in tables — rows and typed columns, like a very strict spreadsheet. Relationships between tables are first-class (this order belongs to that customer), the schema is enforced up front, and you query with SQL, a language from 1974 that has outlived everything built to replace it. Examples: SQLite (a whole database in one file, already on your machine), PostgreSQL and MySQL (the servers behind most of the web).
DocumentData lives as documents — typically JSON objects, grouped into collections, looked up by key. The shape can vary record to record, the schema lives in your code's expectations rather than the database, and it scales horizontally in exchange for weaker cross-record queries. Examples: MongoDB, Amazon DynamoDB, Firestore.
Reach for SQL when…Records relate to each other, you'll ask questions you haven't thought of yet, or correctness rules matter (money, inventory, anything you'd be sued over). The default for almost everything.
Reach for documents when…Records are self-contained blobs with varying shape, you always fetch by key, or you're at a scale where a single SQL server strains. Common in serverless and event-heavy systems.
The honest default

Start every project with SQLite. It's one file, zero setup, real SQL, and it carries further than people expect — many production systems never outgrow it. Graduate to PostgreSQL when you need concurrent writers or a server; add a document store when a specific access pattern demands it, not because it's trendy.

#SQL in ten minutes, on your machine

SQLite ships with macOS and Linux — no install, no server, no account. Open a terminal and type along; this is the whole create-insert-query loop:

sqlite3
$ sqlite3 practice.db
sqlite> CREATE TABLE days (num INTEGER, date TEXT, minutes INTEGER, mode TEXT);
sqlite> INSERT INTO days VALUES (1, '2026-07-07', 60, 'full');
sqlite> INSERT INTO days VALUES (2, '2026-07-08', 15, 'minimum');
sqlite> SELECT * FROM days;
sqlite> SELECT date, minutes FROM days WHERE mode = 'full' ORDER BY date;
sqlite> SELECT mode, COUNT(*), SUM(minutes) FROM days GROUP BY mode;
sqlite> .quit

Four verbs carry most of SQL: SELECT (read), INSERT (add), UPDATE (change), DELETE (remove) — plus WHERE to say which rows, and JOIN to connect tables. The classic beginner disaster is an UPDATE or DELETE without a WHERE: it hits every row. Build the habit now that saves production databases later: run the same condition as a SELECT first, look at what comes back, and only then change it.

look before you write
sqlite> SELECT * FROM days WHERE mode = 'minimum';   -- how many rows? the ones you meant?
sqlite> DELETE FROM days WHERE mode = 'minimum';       -- same WHERE, now it's safe to mean it

#Documents in ten minutes, no install at all

You already know the document model if you've seen JSON — a document store is conceptually "a folder of JSON, indexed, with an API." You can practice the shape with jq on plain files:

documents with jq
$ echo '[{"day":1,"minutes":60,"tags":["shell"]},
        {"day":2,"minutes":15,"tags":["tmux","minimum"]}]' > days.json
$ jq '.[] | select(.minutes > 30)' days.json          # a "query"
$ jq '[.[].minutes] | add' days.json                   # an "aggregation"
$ jq '.[] | select(.tags | contains(["tmux"]))' days.json

Real document databases add what files can't give you: indexes (fast lookup by any field), concurrent access, and durability guarantees. DynamoDB adds one more idea worth knowing early because it inverts SQL thinking: you design the table around your access patterns — decide the questions first, then shape keys so each question is one cheap lookup. SQL lets you ask anything later; Dynamo makes you commit to the questions up front in exchange for flat, predictable speed at any scale.

#Directing agents at data

This is where the two halves of Groundwork meet. Rules that keep agent-written data code safe:

Reads are cheap, writes are decisionsLet an agent draft any SELECT it likes. Any UPDATE, DELETE, DROP, or migration gets read by you, preceded by the matching SELECT, and run against a copy first when the data matters.
Make it show its work"Write the query and a second query that proves it did the right thing." Row counts before and after are the diff review of the data world.
Own the modelAgents implement schemas well and choose them badly. Deciding what the tables or documents are — what's a row, what relates to what, what must never be lost — is judgment work, and it stays yours.
Backups before braverySQLite makes this absurdly easy: cp practice.db practice.backup.db. Do it before any agent-written migration, every time.

#Practice

1

Your log as a database

Create log.db with a days table and enter your last week by hand. Answer with queries: total minutes, days per mode, longest streak of full days. Feel where SQL beats scrolling a text file.

2

The WHERE habit

Insert twenty rows. Practice five UPDATE/DELETE operations, each preceded by its SELECT twin. Then break the rule once on a throwaway copy — run UPDATE days SET minutes = 0; bare — and look at the wreckage. You'll never forget the WHERE again.

3

Same data, both shapes

Model your log both ways: rows in SQLite, documents in a JSON file queried with jq. Write down one question each shape made easy and one it made awkward. That pair of sentences is the whole SQL-vs-document debate in miniature.

#Going deeper

  • SQLBolt — interactive SQL lessons in the browser; the fastest zero-to-queries path.
  • SQLite quickstart — the official five-minute intro to the database you already have.
  • Use the Index, Luke — when you're ready to understand why queries are fast or slow.
  • DynamoDB data modeling — access-pattern-first design, from the source.