DEV Community

Cover image for Sell CRM: Make CRM for every client ❌ | Make CRM core one time and sell every client with rebranding ✅
Saif Ullah Usmani
Saif Ullah Usmani

Posted on

Sell CRM: Make CRM for every client ❌ | Make CRM core one time and sell every client with rebranding ✅

For years, I did the “right” thing, or so I thought.
Every new client, a new CRM. New repo. New schema tweaks. New logic.
It felt productive. It looked busy. It was a trap.

I didn’t learn this from a blog post.
I learned it from production pain, support calls, and my own burnout.


🚧 The early mistake: building for clients, not for scale

When a client asked for a CRM, I’d build their CRM.

Different flows.
Different permissions.
Different custom fields hard-coded because “this client is special.”

On paper:

  • Fast initial delivery
  • Happy client
  • Clean codebase (for now)

In reality:

  • 5 CRMs → 5 slightly different bugs
  • Fixing the same issue 5 times
  • Feature requests that couldn’t be shared
  • Onboarding a new dev became archaeology

The worst part?
Every “small change” had a multiplied cost.


🧠 The uncomfortable realization

The problem wasn’t programming speed.
It was decision duplication.

No-code tools get praised for “speed,” but what they really optimize is:

One core system, many tenants, infinite configurations.

I was doing the opposite:

Infinite systems, tiny differences, zero leverage.

That’s when it clicked:
Programming isn’t slow. Rebuilding the same product over and over is.


🔄 The pivot: one CRM core, many identities (like inheritance in OOP)

Instead of asking:

“How do I build this CRM for this client?”

I started asking:

“What must never change across CRMs?”

That became the CRM Core:

  • Users, roles, permissions (policy-driven, not hard-coded)
  • Pipelines, stages, activities
  • Contacts, companies, deals
  • Audit logs, notifications, access rules
  • Extensible metadata instead of schema forks

Client-specific needs moved to:

  • Config
  • Feature flags
  • Branding
  • Workflow rules
  • Tenant-level permissions

Same engine.
Different paint.
Different defaults.


⚖️ Real tradeoffs (not talked about enough)

This wasn’t a magic win.

What got harder:

  • Initial architecture took longer
  • Over-engineering temptation was real
  • “Just for this client” requests needed discipline
  • Some clients wanted bad ideas — and now I had to say no

What got easier (and compound):

  • Bug fixes once, everywhere
  • New features became revenue, not cost
  • Onboarding a client dropped from weeks to days
  • Support became pattern-based, not detective work
  • Rebranding was a config change, not a rewrite

🔧 Lessons I learned the hard way

  • ❌ Custom code feels fast until version 3
  • ❌ DRY across repos is still duplication
  • ✅ Multi-tenancy is a business decision, not just a technical one
  • ✅ Config > conditionals
  • ✅ Saying “no” to one client can say “yes” to ten future ones
  • ✅ No-code tools don’t beat engineers — systems thinking does

🧩 The maturity shift

Junior me optimized for delivery.
Mid-level me optimized for code quality.
Senior me optimizes for leverage.

Leverage in:

  • Architecture
  • Maintenance cost
  • Team sanity
  • Business scalability

Once you feel the difference, you can’t unsee it.


Closing thought

If you’re rebuilding the same product again and again, you’re not moving fast, you’re running in circles.

Build a core.
Protect it.
Let everything else be replaceable.

That’s not over-engineering.
That’s respect for your future self.

Top comments (0)