What’s behind the API
The kitchen, revealed
Remember the restaurant analogy from the previous chapter? You sit at a table, tell the waiter what you want, and food comes back. You never see the kitchen.
Well, it's time to walk into the kitchen.
When you call GET /users/1, the server doesn't magically conjure up that user. It goes somewhere to look it up. That "somewhere" is a database. Understanding what a database looks like will change how you think about APIs, features, and conversations with your engineering team.
A database is a collection of spreadsheets
Here's the secret: a database is basically a collection of spreadsheets. Seriously.
If you've ever used Excel or Google Sheets, you already understand 80% of how databases work. Let's map the vocabulary:
- A table is a tab in your spreadsheet. One tab for Users, one for Orders, one for Products.
- A row is a record. One user, one order, one product.
- A column is a field. Name, email, plan, created_at.
- The ID column is like the row number, but it never changes, even if you sort or delete rows.
Here's what a Users table might look like:
| id | name | plan | created_at | |
|---|---|---|---|---|
| 1 | Alice Martin | alice@acme.com | pro | 2024-01-15 |
| 2 | Bob Chen | bob@startup.io | free | 2024-02-20 |
| 3 | Clara Diaz | clara@bigcorp.com | enterprise | 2024-03-08 |
| 4 | David Kim | david@freelance.dev | pro | 2024-04-01 |
Nothing scary. It's a spreadsheet with rows and columns. Every app you've ever used has something like this behind it.
The ID column is everything
Notice that every row has an id. That number is the unique identifier for each record. It never changes, and no two rows share the same ID.
This is why API URLs contain IDs. When you call:
GET /users/2
You're saying: "Go to the Users table, find the row where id = 2, and send it back to me."
The server looks up row #2, grabs the data, wraps it in JSON, and sends it back:
{
"id": 2,
"name": "Bob Chen",
"email": "bob@startup.io",
"plan": "free",
"created_at": "2024-02-20"
}
Look at the JSON. Look at the table above. It's the same data, just in a different format. The API response is the spreadsheet row, converted to JSON.
CRUD: the four things you do with a spreadsheet
Think about what you actually do in a spreadsheet. There are only four actions:
- Read a row (or multiple rows)
- Add a new row
- Edit an existing row
- Delete a row
That's it. And those four actions map directly to HTTP methods:
| Action | Spreadsheet | HTTP method | Example |
|---|---|---|---|
| Read | Look at a row | GET | GET /users/2 |
| Create | Add a new row | POST | POST /users |
| Update | Edit a cell | PUT | PUT /users/2 |
| Delete | Delete a row | DELETE | DELETE /users/2 |
Developers call this CRUD (Create, Read, Update, Delete). It sounds technical, but you already know what it means. It's what you do in Excel every day.
Why this matters for PMs
When an engineer tells you something about the API or the backend, they're usually talking about the database. Here's how to translate:
"We don't store that data." There's no column for it. If you want to track "last login date" but there's no last_login column in the Users table, the data simply doesn't exist. Someone needs to add the column and write the code to fill it.
"That field doesn't exist on the user." Same idea. The Users table doesn't have a column called company_name. If you want it in the API response, the database needs to change first.
"We'd need to add a new table." The feature you're asking for involves a type of data that doesn't fit in any existing tab. Think of asking for "user notifications" when there's no Notifications spreadsheet yet.
These aren't excuses. They're real constraints. And now you can picture exactly what they mean.
Try it yourself
Let's make this concrete. DummyJSON's /users endpoint returns data from a Users table. Hit "Send request" to see what a single user looks like:
That's one row from the Users table, filtered to five columns. Now let's get a few rows at once:
Notice the response wraps the rows in a "users" array. That's the API giving you three rows from the table, with just the columns you asked for (select=id,firstName,email).
Every API works like this at its core. A simple endpoint like /users/1 reads from one table. More complex endpoints can pull from several tables at once (an order endpoint might combine data from Orders, Users, and Products). But the principle is the same: the server reads rows from tables and sends them back as JSON.
Key takeaways
- A database is a collection of tables, like tabs in a spreadsheet
- Each row is a record, each column is a field
- The ID uniquely identifies each row. It's why URLs look like
/users/2 - CRUD (Create, Read, Update, Delete) maps directly to GET, POST, PUT, DELETE
- When engineers say "we don't store that," they mean there's no column for it