Heiko Polinski

postgres

A plain-language tour

Where does your data actually live?

No code to write. You will, however, be handed receipts.

The example is a real, small app: a chat window for AI models that kept every conversation inside the browser, until the day that stopped being enough.

The problem a database solves

This chat app used to keep every conversation in a small storage box that browsers offer to websites. The box is called localStorage, and it sits inside one specific browser on one specific machine.

5 MByour laptopthe databaseany other machine
001

The browser's box is tiny.5 MB

About five megabytes in total, for everything. Two AI-generated images and it is full.

5 MByour laptopthe databaseany other machine
002

It sits on one machine.1 browser

The box belongs to one browser on one computer. Open the app anywhere else and there is simply nothing there. No sync, no copy, no way out.

5 MByour laptopthe databaseany other machine
003

And it can vanish.0 backups

Clear your browsing data and your chats are swept out along with the cookies. There is nowhere else they exist.

5 MByour laptopthe databaseany other machine

The fix is to move the data out of the app entirely, into a database: a guarded, organized place that lives on a server on the internet. The size limit effectively disappears, closing the browser deletes nothing, and any machine that logs in sees the same chats.

The cast of characters

Four characters run this show. You will meet them again and again, so here they are with names.

client
001

The client

The app in your browser. It draws what you see and holds a temporary working copy of your data, like papers spread out on a desk.

clientserver
002

The app server

A small middleman program on the internet. It does the things a browser must never do itself, like holding secret keys.

clientserverdatabase
003

The database

The permanent record. Organized, searchable, and strict about its rules. Ours is Postgres, a thirty-year-old classic, rented by the month from a service called Supabase along with the shelf next door and a login desk.

clientserverdatabaseshelf
004

The file storage

A shelf next door for big files, like images. A database is great at small structured facts and bad at big blobs, so the files sit on the shelf and the database keeps a note of where they are.

What a database actually is

Strip away the mystery and a database is a set of spreadsheets with rules.

conversationsidtitle1Trip ideas2Poem draftsmessagesidchattext11Ferry or plane?21Ferry. Slower…32A rhyme for or…one chat, many messages
001

It is just tables and rows.

Each spreadsheet is a table. Each line in it is a row. The chat app has exactly two: one row per conversation, and one row per message.

conversationsidtitle1Trip ideas2Poem draftsmessagesidchattext11Ferry or plane?21Ferry. Slower…32A rhyme for or…one chat, many messages
002

One column does the joining.

Every message carries the id of the conversation it belongs to. That belongs-to column is the relation, and it is the thing that puts the relational in relational database.

conversationsidtitle1Trip ideas2Poem draftsmessagesidchattext11Ferry or plane?21Ferry. Slower…32A rhyme for or…chat 1 deleted, its messages went with it
003

Toss the folder, the pages go too.

Relations can carry rules. This app has one: delete a conversation and its messages are deleted with it, without anybody remembering to clean up. The machine ahead is a real Postgres running inside this page, so press its buttons and watch it happen.

The machine is warming up: a small, real Postgres is loading into this page.

postgres 18 · in your browser · warming up

conversations
idtitle
1Trip ideas
2Poem drafts
messages
idchattext
11Ferry or plane?
21Ferry. Slower, better.
32A rhyme for orange?

The write path: sending a message

When you hit send, four things happen in a deliberately sneaky order. The order is what makes the app feel fast.

screen: instanthalf a second laterwritten for good
001

You hit send.

You type a message and press send. Nothing has left your machine yet.

screen: instanthalf a second laterwritten for good
002

The screen updates first.

The client puts the message on screen immediately. The working copy changes before anything is saved, which is the whole reason the app feels instant.

screen: instanthalf a second laterwritten for good
003

The row rides over.

A moment later the client sends the new data across the wire: insert this message into the messages table.

screen: instanthalf a second laterwritten for good
004

The database writes it down.

Postgres checks its rules first. Is this user allowed? Does this conversation exist? Only then does the row go to disk, and once it is on disk it stays there.

The read path: opening the app

The reverse trip happens every time you open the app, and it is the whole reason the move was worth it.

any machinethe database
001

You log in somewhere new.

A different laptop, a phone, a machine you have never opened the app on. The screen starts empty, because nothing is stored here.

any machinemy chats, pleasethe database
002

The client asks for your rows.

All conversations for this user, newest first, with their messages in order. One question, sent to the database.

any machinemy chats, pleasethe database
003

The database sends them back.

It finds the matching rows and returns them. An index, which is basically a pre-sorted table of contents, keeps this fast even with thousands of rows to look through.

any machinemy chats, pleasethe database
004

The list rebuilds itself.

The client lays the rows out and you get the exact same chat list you left on the other machine. Nothing was copied between the two. Both are just views of the same rows.

Who gets in

There are two layers of doors, and the second one is the good part.

the front doorpass cardthe databaseonly the rows that carry your id
001

The front door checks your password.

Authentication happens at the login desk. Pass, and you are handed a signed pass card, a token, that quietly rides along with every request you make afterwards.

the front doorpass cardthe databaseonly the rows that carry your id
002

A second bouncer waits inside.

Row Level Security is its real name, and it stands inside the database itself. Every table can have a rule attached, and this app uses one: a user may only see and touch rows whose owner column matches their own id.

the front doorpass cardthe databasesame rules, no app in between
003

No way around it.

Even something wired straight to the database, skipping the app entirely, meets the same bouncer. That is exactly what the toggle ahead does: a bare select with no filter, and every row is still checked against the rule before it is handed over. Borrow a pass card and look.

Hold the pass card of

The bouncer is still putting on the jacket: the in-page database is loading.

postgres 18 · in your browser · warming up

chats
idownertitle
1aliceTrip ideas
2alicePoem drafts

The chats table as Alice sees it. Bob's rows are not blurred out or locked. As far as her queries are concerned, they do not exist.

The side shelf: images and tickets

When the AI paints an image in a chat, the picture itself would bloat the database. So it takes a different path.

the private shelfthe imagethe message rowone image15s
001

The image never enters the database.

The server puts it on the storage shelf, next door rather than inside. A database is bad at big blobs and there is no reason to make it carry one.

the private shelfthe imagethe message rowone image15s
002

Only its address goes in the row.

What goes into the message row is a short line of text: where on the shelf to find the picture. The row stays skinny, and the table stays fast.

the private shelfthe imagethe message rowone image15s
003

A ticket lets you look, for a while.

The shelf is private, so the client asks for a signed URL: a temporary link that works like a coat-check ticket. Anyone holding it can view that one image until it expires, and nobody, ticket or not, gets to browse the shelf. The booth ahead hands out fifteen-second ones so you can watch a ticket lapse; the genuine article usually lasts an hour.

On the private shelf

No ticket in hand, so the picture stays on the shelf. Ask for one and watch what you get.

clientserverdatabaseshelf

The whole picture

Every trip through the app is some combination of four short walks. The numbers on the right are the characters from chapter two, so you can see who gets involved in each one.

clientserverdatabaseshelf
  1. 001

    Log in1 · 2

    Client to login desk, pass card back.

  2. 002

    Send a message1 · 2 · 3

    Screen updates instantly, rows ride over a beat later, the bouncer checks each one.

clientserverdatabaseshelf
  1. 003

    Generate an image1 · 2 · 3 · 4

    File to the shelf, note into the table, ticket to your screen.

  2. 004

    Open it anywhere1 · 2 · 3 · 4

    Log in, read your rows, watch the same chats rebuild, fresh tickets for the images.

  3. Everything the app does4 walks

A database turns

my data is trapped in this one browser

into

my data lives in one guarded, organized place, and every screen is just a view of it.