1. Map access patterns to your schema
You’re designing a tiny “social posts” feature. Before you draw any tables or collections, nail what the code will actually do with the data.
Think in terms of user actions → queries. The schema should make those queries simple and fast.
Step 1: List concrete access patterns
For a micro post feature, start with a minimal but realistic set:
-
User timeline
- “Show me my own posts, newest first.”
- Query shape:
- Filter:
author_id = ? - Sort:
created_at DESC - Pagination:
LIMIT 20 OFFSET ?orcreated_at < ? LIMIT 20
- Filter:
-
Profile post list
- “Show this user’s posts on their profile.”
- Almost identical to the timeline above. You might add:
- Optional filter:
visibility IN (...)
- Optional filter:
-
Post detail
- “Open this specific post.”
- Query shape:
- Filter:
post_id = ? - Fetch exactly 1 row/document.
- Filter:
-
Basic moderation / admin
- “Find posts by id or by user for moderation.”
- Query shape:
- Filter:
post_id = ?
orauthor_id = ?with date filters
- Filter:
-
Simple feed
- “Show posts from users I follow” (we’ll keep it naive).
- Query shape:
- Input: a list of
author_ids you follow (say up to 100) - Filter:
author_id IN (...) - Sort:
created_at DESC
- Input: a list of
- (This is not hyper-scalable yet, but good enough for a micro feature.)
From these, you can see that every important query is centered on:
post_idauthor_idcreated_at
Those three should be first-class citizens in your schema.
Step 2: Choose relational vs document shape
For this micro feature, a single main entity — Post — is enough.
You could do:
-
Relational (SQL):
- Table:
posts - Columns:
id,author_id,body,created_at,visibility, etc.
- Table:
-
Document (NoSQL):
- Collection:
posts - Document fields:
_id,author_id,body,created_at,visibility, etc.
- Collection:
In both cases, the logical shape is the same: 1 row/document per post.
Step 3: Draft the basic Post structure
Propose a minimal but practical structure:
| Field | Type | Description |
|---|---|---|
id | UUID / string | Unique post id, primary key |
author_id | UUID / string | User who wrote the post |
body | text | Content, short text |
created_at | timestamp | When the post was created |
visibility | enum | e.g. public, private |
like_count | integer | Aggregate metric for display |
reply_to | nullable id | Parent post id for replies / threads |
How this maps to access patterns:
- User timeline / profile: filter by
author_id, sort bycreated_at. - Post detail: filter by
id. - Moderation: filter by
idor byauthor_id+ date. - Simple feed: filter by
author_id IN (...), sort bycreated_at.
You haven’t written the schema “in the abstract”; you’ve wired it to queries.
If you can’t write your main queries against your draft schema in a single simple SELECT / find call, your schema isn’t aligned with your access patterns yet.