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/smart-phones
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
π― Business Superpower β Multi-Level Product Visibility
A product usually belongs to the deepest (leaf) category.
Example:
Electronics β Mobiles β Smartphones
β
Samsung Galaxy
But customers may browse or search from any level.
They might open:
- Electronics
- Mobiles
- Smartphones
π In all cases, the product should appear.
π§ How This Design Enables It
Because each category stores its path, we instantly know all its ancestors.
Smartphones β path = "1/2/3"
So the product automatically belongs to:
-
1β Electronics -
1/2β Mobiles -
1/2/3β Smartphones
No extra mapping tables.
No complex recursion.
β‘ Example Queries
Show products under Mobiles (including all children)
SELECT p.*
FROM products p
JOIN categories c ON p.category_id = c.id
WHERE c.path LIKE '1/2/%';
This returns items from:
- Smartphones
- Feature Phones
- any future subcategory
Show products under Electronics
WHERE c.path LIKE '1/%';
Boom π₯
Entire department.
π° Business Advantages
β Better product discovery
Users donβt need perfect navigation.
β Faster search & filtering
No recursive joins required.
β Powerful marketing pages
Create pages like:
- βBest Mobilesβ
- βTop Electronics Dealsβ
β Smarter recommendations & ads
Target an entire branch of the catalog.
β Future proof
Add deeper levels anytime β queries still work.
πͺ Real Outcome
If a Samsung Galaxy s23 FE is stored in:
Electronics β Mobiles β Smartphones
It will automatically appear in:
- Electronics listing
- Mobiles listing
- Smartphones listing
- search results
- recommendations
- breadcrumbs
β¨ without extra logic.
π 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 π

Top comments (0)