When building an e-commerce application, categories look simple at first β until your product count grows and business asks for:
- sub-categories
- nested menus
- breadcrumbs
- SEO-friendly URLs
- easy reordering
This README explains a scalable, production-ready category design used in real-world systems, without overengineering.
β The Common Mistake
Many apps start with this:
categories
sub_categories
sub_sub_categories
This breaks immediately when:
- you need more depth
- hierarchy changes
- queries become complex

β
The Scalable Solution (Single Categories Table)
Use one table with a self-reference.
categories
-----------
id UUID / BIGINT (PK)
name VARCHAR(255)
slug VARCHAR(255) UNIQUE
parent_id UUID / BIGINT (FK β categories.id, NULL)
level INT
path VARCHAR(500)
sort_order INT
is_active BOOLEAN
created_at TIMESTAMP
updated_at TIMESTAMP
This supports unlimited nesting and clean queries.
π³ How Hierarchy Works
Example structure
Electronics
βββ Mobiles
βββ Smartphones
βββ Feature Phones
Stored data
| id | name | parent_id | level | path | sort_order |
|---|---|---|---|---|---|
| 1 | Electronics | NULL | 0 | 1 |
1 |
| 2 | Mobiles | 1 | 1 | 1/2 |
1 |
| 3 | Smartphones | 2 | 2 | 1/2/3 |
1 |
| 4 | Feature Phones | 2 | 2 | 1/2/4 |
2 |
π Field Breakdown (The Important Part)
1οΈβ£ slug β URL-friendly identifier
A slug is a readable string used in URLs.
Example:
"Smart Phones" β "smart-phones"
Used for:
/category/electronics/mobiles/smartphones
Why slugs matter:
- SEO friendly
- Stable URLs
- No exposed IDs
2οΈβ£ level β Depth of the category
level tells how deep a category is.
level 0 = root category
level 1 = sub-category
level 2 = sub-sub-category
Why it exists:
- Show only top-level categories on homepage
- Restrict max depth
- Simple filtering
Query example:
SELECT * FROM categories WHERE level = 0;
3οΈβ£ path β Full hierarchy (Materialized Path)
path stores the entire lineage from root β current node.
Example:
Electronics β Mobiles β Smartphones
path = "1/2/3"
Why it’s powerful:
- Fetch entire subtrees without recursion
- Build breadcrumbs easily
- Generate SEO URLs
Query example:
SELECT * FROM categories WHERE path LIKE '1/2/%';
4οΈβ£ sort_order β Display control (NOT hierarchy)
sort_order controls how categories appear in UI.
Without it β unpredictable order
With it β business-controlled order
Query example:
ORDER BY sort_order ASC;
Used for:
- Navbar ordering
- Featured categories
- Seasonal rearrangements
π‘ Why Use level + path Together?
| Use case | level | path |
|---|---|---|
| Top-level filtering | β | β |
| Max depth validation | β | β |
| Subtree queries | β | β |
| Breadcrumbs | β | β |
| SEO URLs | β | β |
They solve different problems, not duplication.
π Product Association
Products usually belong to the leaf category.
products
---------
id
name
slug
price
category_id β categories.id
π Final Recommendation
- β
Single
categoriestable - β
parent_idfor structure - β
levelfor depth logic - β
pathfor fast reads - β
slugfor clean URLs - β
sort_orderfor UI control
This design scales from startup MVP β large marketplace without schema changes.
π¬ Interview One-Liner
A scalable category system uses a self-referencing table with materialized paths to support unlimited depth, fast reads, clean URLs, and UI-controlled ordering.
If you liked this design, feel free to β the repo or reuse it in your project.
Happy building π
