Where does your app actually store data? Databases, explained
In one sentence:A database is where your app's information actually lives after you close the tab, organized into tables so it can be found, trusted, and shared by many users at once.
What it actually is
A database is a program that stores your app’s data in an organized, searchable way and hands it back out reliably, even when many people ask at once. Think of it like a library with a card catalog instead of a pile of books on the floor. You don’t dig through everything to find “Marcus, order #4521, delivered March 3rd.” You ask a specific question and the database’s index points straight to the answer.
Most apps use a relational database: data organized into tables, like tabs in a spreadsheet. A users table has columns (id, email, created_at) and rows, one per person. An orders table links back to users through a shared user_id column, called a foreign key. That’s the payoff of the relational model: data lives in one place, and other tables reference it instead of duplicating it everywhere.
When people say “Postgres” or “MySQL,” they mean the engine actually reading and writing the data to disk. “Supabase” is Postgres with a hosting service, a dashboard, a login system, and auto-generated APIs wrapped around it, not a separate kind of database. When your AI sets up Supabase, it’s still building normal Postgres tables underneath; Supabase is the box it comes in.
Why your AI just did this
Your agent reaches for a database the moment your app needs to remember something after the browser tab closes. A to-do list that resets every time you refresh is living only in memory, not a database. The instant you ask for “let users sign up,” “save their preferences,” or “keep the cart contents,” it needs a place that survives restarts, page reloads, and different people using the app from different devices. A plain JavaScript variable or localStorage can’t do that.
It also reaches for one when several things need to agree on the truth at once. If two people can edit the same document, or an order status has to match what payment processing recorded, that needs the transactional guarantees a real database gives you, so two updates don’t collide and corrupt each other.
When you’ll run into it
You’ll see it during setup, when your agent says something like “I created a profiles table with columns for id, username, and avatar_url.” That’s the schema, the blueprint for what one row of data looks like.
You’ll see it in error messages: relation "orders" does not exist means the table hasn’t been created yet, usually because a migration didn’t run. duplicate key value violates unique constraint means you tried to insert a row that breaks a rule, like signing up with an email that’s already taken.
You’ll see it when your agent asks you to run a migration: a script that changes the database’s structure (add a column, rename a table) without erasing what’s already stored. And you’ll see it in the Supabase dashboard itself: a spreadsheet-like table browser showing the actual rows your users created.
What to check
- Open the table browser (Supabase’s Table Editor or similar) and look at real rows. Confirm data is landing where you think it is
- Check whether sensitive columns store plain text. Passwords should be hashed, and card numbers shouldn’t be stored in your database at all; use tokens from a processor like Stripe instead
- Ask who besides your app can read this table. With Row Level Security off, anyone holding your project’s public API key can query it directly
- Before running a migration on real user data, have your agent confirm it won’t drop or overwrite existing rows
- Check that backups exist and how far back they go. Many free-tier plans don’t include them, so confirm in your provider’s dashboard (Supabase: Database > Backups)
Say it like a dev
Instead of: “Where does the app remember stuff?” Say: “Which table is this stored in, and what does the schema look like?”
Instead of: “Make the login page work.”
Say: “Set up a users table with auth, and show me the schema before you run the migration.”
Instead of: “Why did saving break?” Say: “Is this a database error, or is it failing before the request even reaches the database?”
People actually ask
“Where do my users' data actually live?”
In the database your app is connected to. For most vibe-coded apps that's a Postgres database hosted by a provider like Supabase or Neon. Open that provider's table browser and you can see the literal rows: the data isn't floating inside your app's code, it's sitting on their servers in tables you can inspect anytime.
“What is Supabase actually?”
It's a hosted Postgres database bundled with extras (a login/auth system, file storage, auto-generated APIs, and a dashboard) so you don't have to install, secure, and maintain a database server yourself. When your AI says "I set up Supabase," it's creating standard Postgres tables you could just as easily run on another host.
“Do I even need a database if my app is simple?”
Only if it needs to remember something between visits or across users. A single-user tool that resets on refresh can get by without one, but the moment you add "save my settings" or "let two people see the same list," you need a real database.
Related terms
Glim can explain your sessions, live.
The app watches your coding agent and narrates it in plain words. Waitlist is open.