Resources and relationships
One table isn't enough
In the previous lessons, we looked at single tables: Users, Products. But real apps don't have one table. They have dozens, sometimes hundreds, all connected to each other.
Think about Uber. There's a Users table, a Drivers table, a Rides table, a Payments table, a Ratings table. Each one holds different data, but they all reference each other. A ride belongs to a user and a driver. A payment belongs to a ride. A rating belongs to a ride too.
These connections between tables are called relationships. And they're the reason your engineer sometimes says "that's more complicated than it sounds."
Relationships, the spreadsheet way
Let's look at two tables. First, a simple Users table:
| id | name | |
|---|---|---|
| 1 | Alice Martin | alice@acme.com |
| 2 | Bob Chen | bob@startup.io |
| 3 | Clara Diaz | clara@bigcorp.com |
Now an Orders table:
| id | user_id | product | total | status |
|---|---|---|---|---|
| 101 | 1 | Wireless Mouse | 2500 | delivered |
| 102 | 1 | USB-C Hub | 4500 | shipped |
| 103 | 2 | Desk Lamp | 3200 | delivered |
| 104 | 3 | Keyboard | 8900 | processing |
| 105 | 3 | Monitor Stand | 5500 | delivered |
See the user_id column? That's the link. Order #101 has user_id: 1, which means it belongs to Alice (id = 1 in the Users table). Order #103 has user_id: 2, so it belongs to Bob.
If you use spreadsheets, this is like a VLOOKUP. The user_id column says "go to the Users table and find the row with this ID." That's how databases connect tables together.
This one relationship answers tons of questions:
- "What are Alice's orders?" → filter Orders where
user_id = 1 - "Who placed order #104?" → look up
user_id = 3→ Clara - "How many orders does Bob have?" → count rows in Orders where
user_id = 2→ one
Nested routes
REST conventions have a way to express these relationships in URLs. They're called nested routes:
GET /users/1/posts
Read it left to right: "Go to Users, find user #1, then get their posts." The URL mirrors the relationship in the database.
Let's try it. DummyJSON supports nested routes. Here are user #1's posts:
Now user #1's todos:
And the comments on post #1:
The pattern is always the same: /parent/id/children. The URL tells you exactly which relationship you're following. Once you know the resource names, you can often guess the nested route without reading the docs.
Why your engineer says "that's complicated"
Now for the practical part. You're a PM, you have a feature idea, and your engineer says "that's more complicated than you think." Here are three scenarios that explain why.
Scenario 1: "Show order history on the user profile"
Your Users table and Orders table are already connected by user_id. The relationship exists. The data is there. The engineer just needs to call GET /users/1/orders and display the results.
Verdict: straightforward. The data model already supports it.
Scenario 2: "Let users favorite products"
Right now, you have a Users table and a Products table. But there's no connection between them for favorites. Where do you store the fact that Alice favorited the Wireless Mouse?
You can't just add a favorites column to the Users table. What would it contain? A list of product IDs? That breaks how databases work (one value per cell, just like a spreadsheet).
The answer: you need a new table.
| id | user_id | product_id | created_at |
|---|---|---|---|
| 1 | 1 | 42 | 2024-06-10 |
| 2 | 1 | 17 | 2024-06-11 |
| 3 | 2 | 42 | 2024-06-12 |
| 4 | 3 | 8 | 2024-06-15 |
This is a Favorites table. Each row means "this user favorited this product on this date." Alice (user 1) favorited products 42 and 17. Bob (user 2) also favorited product 42.
This pattern is called many-to-many: many users can favorite many products, and many products can be favorited by many users. It always requires a new table in the middle.
That's why the engineer says it's complicated. It's not just showing data. It's creating a whole new table, new endpoints (GET /users/1/favorites, POST /users/1/favorites, DELETE /users/1/favorites/42), and new logic.
Scenario 3: "Add tags to products"
Sounds simple, right? "Just add a tags field." But think about it: a product can have many tags, and a tag can belong to many products. That's many-to-many again. You need:
- A Tags table (id, name)
- A ProductTags table (id, product_id, tag_id)
Two new tables for what sounded like "just a field." This is why PMs who understand data models write better specs and have more productive conversations with engineers.
Key takeaways
- Real apps have many tables connected through ID references (like
user_id) - A
user_idcolumn in Orders is like a VLOOKUP to the Users table - Nested routes (
/users/1/posts) express these relationships in URLs - Many-to-many relationships (favorites, tags) always require a new table
- When an engineer says "it's complicated," they often mean the data model needs to change