# Rethinking Product Variants: From One Product to Many

All I wanted to do was support something *simple*:

> A seller should be able to list banana bread…  
> with and without choco chips… at different prices.

That’s it.

But somehow, this turned into:

*   product vs variant debates
    
*   option vs attribute confusion
    
*   structured vs flexible nightmares
    

Classic overengineering spiral.

### The Bakery Thought Experiment

Then I imagined something very real.

You walk into a bakery.

Behind the glass, you see:

*   Banana Bread = ₹199
    
*   Banana Bread with Choco Chips = ₹249
    

They’re sitting right next to each other.  
Different trays. Different prices. Same base item.

And your brain doesn’t go:

> “Ah yes, this is one product with two variants.”

No.

Your brain goes:

> “There are two things I can buy.”

### That’s when it clicked

The problem wasn’t technical.

It was how I was *thinking* about the model.

I was forcing everything into:

> “One product → many variants”

But in reality, what I had was:

*   **One Offering** (Banana Bread)
    
*   **Multiple purchasable Products**
    

### The Mental Model Shift

Instead of this:

```plaintext
Product
  └── Variants (500gm, 1000gm, choco chips, etc.)
```

I moved to this:

```plaintext
Offering (Banana Bread)
  ├── Product → Classic → ₹199
  └── Product → With Choco Chips → ₹249
```

Each variant is not a “child object”.

It’s a **real product**.

Something you can:

*   price independently
    
*   track inventory for
    
*   show directly to users
    

### Where It Gets Messy

Then came the real problem.

How do you handle:

*   size (500gm, 1000gm)
    
*   dimensions (20x30 cake)
    
*   weird stuff like “extra toppings” or "added cheese"
    

I tried two extremes:

1\. Everything structured

```plaintext
quantity: 500
unit: gm
dimensions: {...}
```

Clean. Queryable. Backend-friendly.

But…

> Where does “extra toppings” go?

2\. Everything flexible (options)

```plaintext
Flavor: Butterscotch
Size: 500gm
```

Flexible. Easy to extend.

But…

> Now you can’t filter, sort, or reason about anything properly.

### The Balance That Actually Works

So I stopped trying to be perfect.

And split things into 3 layers:

#### 1\. Structured fields (for the system)

*   quantity
    
*   unit
    
*   dimensions
    
*   weight
    

Used for:

*   filtering
    
*   logistics
    
*   analytics
    

#### 2\. Label (for humans)

This is the most important field.

What the customer actually sees:

*   “500gm”
    
*   “With Choco Chips”
    
*   “Large”
    

This becomes the **single source of truth for display**

#### 3\. Optional custom options (for edge cases)

Only when needed:

*   Flavor → Butterscotch
    
*   Topping → Extra Nuts
    

Not forced. Not everywhere. Just when it makes sense.

### The UI Changed Everything

Instead of complex variant builders…

I made it stupid simple:

```plaintext
*[ Label ]        → "With Choco Chips"
*[ Price ]        → ₹249

[ Quantity ]     → 500 gm
[ Dimensions ]   → L x W x H

[ Add custom option ]
  Flavor → Butterscotch
                                            [+ Add Variant]
```

And that’s it.

### The Unexpected Truth

Most sellers don’t care about your schema.

They will just type:

*   “Banana Bread”
    
*   “₹199”
    

And move on.

They don’t wake up thinking:

> “Should I define an option group with normalized values?”

They just want to list and sell.

### Real moments where they pause

*   When price changes  
    → “Wait, choco chips costs more”
    
*   When the choice is obvious  
    → “Small vs Large”  
    → “500gm vs 1kg”
    
*   When customers usually ask  
    → “Do you have eggless?”  
    → “Do you add nuts?”
    
*   When it affects decision-making  
    → “Full hands mehendi vs half hands”  
    → “Basic vs premium package”
    

In those moments, something shifts.

They pause and think:

> “Okay… I should probably show this as an option.”

Not because your system told them to;  
but because **their customer expects it**.

### And the UI should meet them right there

No complex setup. No forced structure.

Just a simple:

> **\[ + Add Variant \]**

They click it… and add:

*   a new **label** → “With Choco Chips”
    
*   a new **price** → ₹249
    
*   (optionally) more details if they care
    

No “define option groups”  
No “configure attributes”  
No mental overhead

Just:

> “Here’s another version of the same thing I’m selling.”

### The Real Lesson

> Variants shouldn’t feel like configuration.  
> They should feel like *adding another item to the shelf!*

### Final Takeaway

Stop trying to design the “perfect” variant system.

Instead:

*   Model real-world behavior
    
*   Keep data readable
    
*   Allow flexibility without forcing it
    

That bakery shelf taught me more than hours of schema design ever did.

[Panchhee](https://panchhee.in) isn't trying to be the most powerful marketplace.

> It's trying to be the simplest one.

There are already countless marketplaces for complex setups; Panchhee is for people who just want to list and sell.

Happy Building!
